Why when use enable_if in class tempalte have to set the second parameter's default type as void?

I’m currently studying enable_if.
But I have this code:

//template<typename T, typename = int/double/float/...> //not working properly
template<typename T, typename = void> //works fine
struct test{
    void func(){
        cout << "default" << endl;
    }
};
template<typename T>
struct test<T, typename std::enable_if<(sizeof(T) <= 1)>::type>{
    void func(){
        cout << "called" << endl;
    }
};
int main() {
    test<char> objs1;
    objs1.func(); //called
    test<int> objs2;
    objs2.func(); //default
}

I don’t know the reason why I have to set the second parameter’s default value as void. If I set it to other values like int or float or double, both objs1.func(); and objs2.func(); will print default. What is the reason?

>Solution :

So, std::enable_if<...>::type is, in fact, a type. Because you didn’t specify what the type should be, you just specified the condition for which it exists at all, the default is void.

Let’s look at your second version of the template. If sizeof(T) <= 1, you provide a template specialization for test<T, void>. Otherwise, the substitution fails and you provide nothing.

Now let’s consider what happens when you just write test<char> objs1;. In your original version, because the default value for the unnamed second template parameter was void, this means objs1 is actually of type test<char, void>. And we actually have a specialization for test<char, void>, because sizeof(char) <= 1 is true.

However, if you change the default value of the unnamed second template parameter, we get a very different situation. Say you make the default value int instead of void. Then test<char> objs1; is actually declaring an object of type test<char, int>. We have a specialization defined for test<char, void>… But we aren’t trying to create a test<char, void>, we’re trying to create the separate type test<char, int>. So the fact that the condition of the enable_if is true is neither here nor there and we get the default definition of test.

Leave a Reply