Почему ошибка компиляции с enable_if

Почему это не компилируется с gcc48 и clang32?

#include <type_traits>

template <int N>
struct S {

template<class T>
typename std::enable_if<N==1, int>::type
f(T t) {return 1;};

template<class T>
typename std::enable_if<N!=1, int>::type
f(T t) {return 2;};
};

int main() {
S<1> s1;
return s1.f(99);
}

Ошибка GCC:

/home/lvv/p/sto/test/t.cc:12:2: error: no type named ‘type’ in ‘struct enable_if<false, int>’
f(T t) {return 2;};
^

Ошибка CLANG:

/home/lvv/p/sto/test/t.cc:11:26: error: no type named 'type' in 'std::enable_if<false, int>'; 'enable_if' cannot be used to
disable this declaration
typename std::enable_if<N!=1, int>::type
^~~~
/home/lvv/p/sto/test/t.cc:16:7: note: in instantiation of template class 'S<1>' requested here
S<1> s1;
^

РЕДАКТИРОВАТЬ — РЕШЕНИЕ

Я принял ответ от Чарльза Сальвии, но по практическим причинам я не смог использовать предложенный обходной путь (специализируюсь на N). Я нашел другой обходной путь, который работает для меня. Делать enable_if зависит от T:

typename std::enable_if<(sizeof(T),N==1), int>::type

25

Решение

Потому что вы используете enable_if без использования параметра шаблона T в ваших шаблонах функций. Если вы хотите специализироваться на том, когда структура S имеет определенное значение параметра шаблона Nвам нужно будет использовать специализацию шаблона класса.

template <int N, class Enable = void>
struct S {  };

template <int N>
struct S<N, typename std::enable_if<N == 1>::type>
{
....
};
17

Другие решения

Ну, я не уверен, что вы хотели сделать, но, возможно, этот код поможет:

#include <iostream>

template <int N>
struct S {

template<class T=int>
typename std::enable_if<N==1, T>::type
f(T t) {return 1;}

template<class T=int>
typename std::enable_if<N!=1, T>::type
f(T t) {return 2;}
};

int main()
{
S<1> s1;
S<2> s2;
std::cout << s1.f(99) << " " << std::endl << s2.f(5);
}

Это печатает 1 и 2.

9

Используйте параметр логического шаблона по умолчанию, например:

template <int N>
struct S {

template<class T, bool EnableBool=true>
typename std::enable_if<N==1 && EnableBool, int>::type
f(T t) {return 1;};

template<class T, bool EnableBool=true>
typename std::enable_if<N!=1 && EnableBool, int>::type
f(T t) {return 2;};
};
8

Получить std::enable_if чтобы работать так, вы полагаетесь на SFINAE. К сожалению, в тот момент, когда вы объявляете

S<1> s1;

это будет создавать все S<1>декларации участника. SFINAE вступит в игру только в том случае, если S<1> были плохо сформированной конструкции. Это не. К сожалению, он содержит функцию, которая является недопустимой, таким образом S<> является недействительным.

Для таких вещей я мог бы отложить отдельную структуру шаблона:

template <bool B>
struct f_functor {
template <typename T>
static int f(T t) { return 1; }
};

template <>
struct f_functor<false> {
template <typename T>
static int f(T t) { return 2; }
};

template <int N>
struct S {

template<class T>
typename int f(T t) { return f_functor<N==1>::f(t); }
};
5

В этом случае вы можете подумать о том, чтобы вообще не использовать enable_if. Можно просто специализировать f:

template <int N>
struct S {
template<class T> int f(T t);
};

template<int N>
template<class T>
int S<N>::f(T t) { return 2; }

template<>
template<class T>
int S<1>::f(T t) { return 1; }

int main() {
S<1> s1;
return s1.f(99);
}
1
По вопросам рекламы [email protected]