Magus
Magus

Reputation: 15104

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.

Upvotes: 5

Views: 1746

Answers (2)

songyuanyao
songyuanyao

Reputation: 172864

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

Upvotes: 6

Dmitry Gordon
Dmitry Gordon

Reputation: 2324

You need to use std::enable_if in function argument instead of a template parameter:

// Declaration
template <typename T>
void test(T& value, enable_if_t<is_class<T>::value>* = nullptr);

template <typename T>
void test(T& value, enable_if_t<!is_class<T>::value>* = nullptr);

template <>
void test<int>(int& value, enable_if_t<!is_class<int>::value>*);

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

template <typename T>
void test(T& value, enable_if_t<!is_class<T>::value>*) {
    cout << "Other types test" << endl;
}

template <>
void test<int>(int& value, enable_if_t<!is_class<int>::value>*) {
    cout << "int test" << endl;
}

Upvotes: 0

Related Questions