I am trying to write a function template. One version should be used for all types that don’t satisfy the criteria for the other version; the other version should be used when the argument is a base class of a given class, or that class itself.
I have tried doing an overload for Base&, but when classes are derived from Base, they use the general one, not the specific one.
I also have tried this SFINAE approach:
struct Base { };
struct Derived : public Base { };
struct Unrelated { };
template<typename T>
void f(const T& a, bool b = true) {
cout << "not special" << endl;
}
template<typename T>
void f(const Base& t, bool b = is_base_of<Base, T>::value) {
cout << "special" << endl;
}
Base b;
Derived d;
Unrelated u;
f(b); f(d); f(u);
But all of them print “not special”. I am not good at SFINAE and I am probably just doing it wrong. How can I write a function like this?
First, none of these will ever call the “special”
foverload becauseTcannot be deduced from the function arguments. Its first parameter needs to be of typeT:Once that is done, note that the “special” overload doesn’t really use SFINAE to affect overload resolution:
is_base_of<T, U>::valuealways has a value: it’s eithertrueorfalse. To affect overload resolution, you need to useenable_if, which conditionally defines a type based on a boolean value.Also, both overloads need to use SFINAE: the “special” overload must be enabled if
Tis derived from the base (or is the base type), and the “not special” overload must be enabled only ifTis not derived from the base, otherwise there will be overload resolution ambiguities.The two overloads should be declared and defined as:
Finally, note that there is no specialization here. These two functions named
fare overloads.