为什么这不能用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);
}
海湾合作委员会错误:
/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;
^
编辑 - 解决方案
我接受了Charles Salvia的回答,但由于实际原因,我无法使用提议的解决方法(专注于N)。我找到了适合我的其他解决方法。让enable_if
取决于T
:
typename std::enable_if<(sizeof(T),N==1), int>::type
答案 0 :(得分:18)
因为您在功能模板中未使用模板参数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>
{
....
};
答案 1 :(得分:10)
嗯,我不确定你想做什么,但也许这段代码会有所帮助:
#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.
答案 2 :(得分:8)
使用默认的布尔模板参数,如下所示:
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;};
};
答案 3 :(得分:5)
要让std::enable_if
像这样工作,您依赖的是SFINAE。不幸的是,在你宣布
S<1> s1;
它将实例化所有S<1>
的成员声明。如果S<1>
是一个构造不良的构造,SFINAE只会在此时发挥作用。它不是。不幸的是,它包含一个无效的函数,因此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); }
};
答案 4 :(得分:1)
对于这种情况,您可以考虑不使用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);
}