1
votes

I have below code that I want TestEnableIf with different specialization to have different print function, but it didn't work out as planned, with error as below.

struct myStruct;
struct notMyStruct;

template<typename T> struct TestEnableIf
{
        template<typename boost::enable_if< boost::is_same<myStruct, T>, int >::type = 0> void print()
        {
            std::cout << "this is my struct" << std::endl;
        }

        template<typename boost::enable_if< boost::is_same<notMyStruct, T>, int>::type=0> void print()
        {
            std::cout << "This is not my struct" << std::endl;
        }


};

static void testIsSame()
{

    TestEnableIf<myStruct> testEnable;
     testEnable.print();
     TestEnableIf<notMyStruct> testNotEnable;
     testNotEnable.print();
}

../src/testBoostGeneric.h:39:90: error: no type named ‘type’ in ‘struct boost::enable_if, int>’ template, int>::type=0> void print() ^ ../src/testBoostGeneric.h: In instantiation of ‘struct TestEnableIf’: ../src/testBoostGeneric.h:53:29:
required from here ../src/testBoostGeneric.h:34:90: error: no type named ‘type’ in ‘struct boost::enable_if, int>’ template, int >::type = 0> void print()

What I don't understand is, should sfinae mean specialization failure is not an error, then why should the compiler complain about the failure?

1

1 Answers

4
votes

SFINAE (the S is "substitution", not "specialization", by the way) for member functions does not work this way with class type parameters. A simple way to get around that is to use another template parameter:

template<
    typename TCopy = T
    typename boost::enable_if< boost::is_same<myStruct, TCopy>, int >::type = 0
> void print()
{
    std::cout << "this is my struct" << std::endl;
}

I pulled this from STL's CppCon talk. TL;DW: when using the class's T type parameter, the compiler knows what that type is when instantiating the class template and would check for the type member at that point in time. With the extra TCopy type parameter being local to the function, the compiler cannot know for sure until the function is instantiated, at which point SFINAE can jump in to affect the overload set for the call.