I'm trying to understand how to select the right overloaded function template at compile-time, but the compiler is giving me a hard time. I can make it work, but I don't understand what is going on. Let me explain.
I have two structs A and B like below. One has a special function and the other a normal.
struct A
{
void special() { std::cout << "special called.\n"; }
};
struct B
{
void normal() { std::cout << "normal called.\n"; }
};
My intension is to have a mechanism, which at compile-time selects the right overloaded function template depending on if the special function is available. I have two functions run, which take the struct as a parameter, so they can call the appropriate function.
template<class Func, Func f> struct Sfinae {};
template <typename U>
static void run(U& u, Sfinae<void (U::*)(), &U::special>* = 0)
{
u.special();
}
template <typename U>
static void run(U& u, ...)
{
u.normal();
}
I've tested this with the following, with various results:
int main()
{
A a;
run<A>(a, 0); // works
run<A>(a); // ERROR: ambiguous overloaded function
run(a, 0); // ERROR: A has no member normal
run(a); // ERROR: ambiguous overloaded function
B b;
run<B>(b, 0); // works
run<B>(b); // works
run(b, 0); // works
run(b); // works
return 0;
}
I'd like to use it as run(a)
without any extra argument or <>. Is there something wrong with my code when this is not working?
Also, I'm interested to understand what is going on here and why this is deducing things like this, so I need to give <A>
for A
but not for B
? I don't know what the standard says and if this is different between compilers, but at least gcc4.4.4 on Linux and gcc 4.0.1 on Mac work like I've described.
Can someone please shed some light on this? Thanks!
This here will work. It sort-of assumes that the two functions normal and special are mutually exclusive (i.e. a class that has one of them doesn't have the other). I'm sure you can adapt it to your purpose. This uses
boost::enable_if
, of course.This works on gcc 4.6.0 on Linux.