Search code examples
c++c++11templatestemplate-specializationenable-if

Template specialization with enable_if


I'm trying to create a template function taking a typename. I want to specialize this templates for some basic types like int, long, string and double. For all others types, i need to have a specialized code for class/struct, and a default code for others types.

My current code is this one :

// Declaration
template <typename T, typename enable_if<is_class<T>::value>::type = 0>
void test(T& value);

template <typename T, typename enable_if<!is_class<T>::value>::type = 0>
void test(T& value);

template <> // What am i supposed to write here ?
void test<int>(int& value);

// Definition
template <typename T, typename enable_if<is_class<T>::value>::type = 0>
void test(T& value) {
    cout << "Class/struct test" << endl;
}

template <typename T, typename enable_if<!is_class<T>::value>::type = 0>
void test(T& value) {
    cout << "Other types test" << endl;
}

template <>
void test<int>(int& value) {
    cout << "int test" << endl;
}

This code won't compile. I can't figure what am i suppoed to write in the int specialized template.

I'm trying to use the examples from this documentation, but i'm unable to make it work.


Solution

  • typename enable_if<is_class<T>::value>::type = 0 doesn't make sense, because typename enable_if<is_class<T>::value>::type would refer to void; you can change it to typename enable_if<is_class<T>::value>::type* = nullptr. Then for the full specialization for int, note that test has two template parameters, then

    // Declaration
    template <typename T, typename enable_if<is_class<T>::value>::type* = nullptr>
    void test(T& value);
    
    template <typename T, typename enable_if<!is_class<T>::value>::type* = nullptr>
    void test(T& value);
    
    template <>
    void test<int, nullptr>(int& value);
    
    // Definition
    template <typename T, typename enable_if<is_class<T>::value>::type*>
    void test(T& value) {
        cout << "Class/struct test" << endl;
    }
    
    template <typename T, typename enable_if<!is_class<T>::value>::type*>
    void test(T& value) {
        cout << "Other types test" << endl;
    }
    
    template <>
    void test<int, nullptr>(int& value) {
        cout << "int test" << endl;
    }
    

    LIVE

    Or simply put typename enable_if<is_class<T>::value>::type as the return type. e.g.

    // Declaration
    template <typename T>
    typename enable_if<is_class<T>::value>::type test(T& value);
    
    template <typename T>
    typename enable_if<!is_class<T>::value>::type test(T& value);
    
    template <>
    void test<int>(int& value);
    
    // Definition
    template <typename T>
    typename enable_if<is_class<T>::value>::type test(T& value) {
        cout << "Class/struct test" << endl;
    }
    
    template <typename T>
    typename enable_if<!is_class<T>::value>::type test(T& value) {
        cout << "Other types test" << endl;
    }
    
    template <>
    void test<int>(int& value) {
        cout << "int test" << endl;
    }
    

    LIVE