views:

183

answers:

1

Hi Everyone,

I'm trying to use SFINAE to detect if a class has an overloaded member function that takes a certain type. The code I have seems to work correctly in Visual Studio and GCC, but does not compile using the Comeau online compiler.

Here is the code I'm using:

#include <stdio.h>

//Comeau doesnt' have boost, so define our own enable_if_c
template<bool value> struct enable_if_c { typedef void type; };
template<> struct enable_if_c< false > {}; 


//Class that has the overloaded member function
class TestClass
{
public:
    void Func(float value) { printf( "%f\n", value ); }
    void Func(int value) { printf( "%i\n", value ); }
};


//Struct to detect if TestClass has an overloaded member function for type T
template<typename T>
struct HasFunc
{
    template<typename U, void (TestClass::*)( U )> struct SFINAE {};
    template<typename U> static char Test(SFINAE<U, &TestClass::Func>*);
    template<typename U> static int Test(...);
    static const bool Has = sizeof(Test<T>(0)) == sizeof(char);
};


//Use enable_if_c to only allow the function call if TestClass has a valid overload for T
template<typename T> typename enable_if_c<HasFunc<T>::Has>::type CallFunc(TestClass &test, T value) { test.Func( value ); } 

int main()
{
    float value1 = 0.0f;
    int value2 = 0;
    TestClass testClass;
    CallFunc( testClass, value1 );  //Should call TestClass::Func( float )
    CallFunc( testClass, value2 );  //Should call TestClass::Func( int )
}

The error message is: no instance of function template "CallFunc" matches the argument list. It seems that HasFunc::Has is false for int and float when it should be true.

Is this a bug in the Comeau compiler? Am I doing something that's not standard? And if so, what do I need to do to fix it?


Update moved here from answer below:

I guess the question now becomes, if this is a bug, is there anything I can do to work around it? I tried using a static_cast on &TestClass::Func, but either that isn't possible or I didn't get the syntax right because I couldn't get it to compile.

If that's not a solution, is there any modifications I can make either to TestClass or HasFunc in order to work around the issue?

A: 

I suspect the problem is that as TestClass overloads Func and the Comeau compiler is unable to disambiguate &TestClass::Func, even it it should.

Vicente Botet Escriba
The correct overload should be selected through the function pointer argument type in `SFINAE` - `void (TestClass::*)(U)`.
Georg Fritzsche
My bad. It works also with MinGW gcc 4.4. In cygwin gcc 3.4.4 produce a compiler internal error.
Vicente Botet Escriba
gcc-3.4.4 produce the error: two or more data types in declaration of `CallFunc'Well my suspicion seems to be correct. Comeau should have the same problem than gcc-3.4.4.
Vicente Botet Escriba