Почему ошибка компиляции с включить если
Почему это не компилируется с 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;};
^
Ошибка лязга:
/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;
^
EDIT-SOLUTION
Я принял ответ от Чарльза Сальвиа, но по практическим причинам я не смог использовать предложенный обходной путь (специализируюсь на N). Я нашел другой обходной путь, который работает для меня. Сделатьenable_if
зависимым от T
:
typename std::enable_if<(sizeof(T),N==1), int>::type
5 ответов:
Потому что вы используете
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> { .... };
Ну, я не уверен, что вы хотели сделать, но, возможно, этот код поможет:
#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.
Используйте параметр шаблона boolean по умолчанию, например:
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;}; };
Чтобы заставить
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); } };
В этом случае вы можете подумать о том, чтобы вообще не использовать 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); }