views:

109

answers:

1

I know how to specialise a template function, however what I want to do here is specialise a function for all types which have a given method, eg:

template<typename T> void foo(){...}

template<typename T, if_exists(T::bar)>void foo(){...}//always use this one if the method T::bar exists

T::bar in my classes is static and has different return types.

I tried doing this by having an empty base class ("class HasBar{};") for my classes to derive from and using boost::enable_if with boost::is_base_of on my "specialised" version. However the problem then is that for classes that do have bar, the compiler cant resolve which one to use :(.

template<typename T>
typename boost::enable_if<boost::is_base_of(HasBar, T>, void>::type f()
{...}

I know that I could use boost::disable_if on the "normal" version, however I do not control the normal version (its provided by a third party library and its expected for specialisations to be made, I just don't really want to make explicit specialisations for my 20 or so classes), nor do I have that much control over the code using these functions, just the classes implementing T::bar and the function that uses it.

Is there some way to tell the compiler to "always use this version if possible no matter what" without altering the other versions?

EDIT: I tried a different approach using a template class and explicit specialisations, but this is apparently also not allowed...Anyway to make this approach work?

template<typename T>class ImpFoo
{
public:
    //error C3637: 'foo' : a friend function definition cannot be a specialization of a function template
    template<> friend void foo<T>(){...}
};
...
class SomeClass : public ImpFoo<T>
{
...
    SomeType bar(){...}
};
+1  A: 

Sadly you are out of luck in this situation as descriped, the best thing you can do is to explicitly specialize the templates as @aaa says.
As you can limit these specializations to a simple forwarding to one central function, the overhead for 20 classes should be bearable. E.g.:

template<class T> my_foo() { /* do the actual work */ }

template<> void foo<MyClass01>() { my_foo<MyClass01>(); }
// ...
template<> void foo<MyClass20>() { my_foo<MyClass20>(); }
Georg Fritzsche