C++ 为什么使用 enable_if 编译错误
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13964447/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why compile error with enable_if
提问by Leonid Volnitsky
Why this does not compile with gcc48 and clang32?
为什么这不能用 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 error:
海湾合作委员会错误:
/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 error:
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;
^
EDIT - SOLUTION
编辑 - 解决方案
I've accepted answer from Charles Salvia, but for practical reasons I was not able to use workaround that was proposed (specialize on N). I found other workaround which works for me. Make enable_if
depend on T
:
我已经接受了 Charles Salvia 的回答,但出于实际原因,我无法使用提出的解决方法(专门针对 N)。我找到了其他对我有用的解决方法。使enable_if
依赖于T
:
typename std::enable_if<(sizeof(T),N==1), int>::type
采纳答案by Charles Salvia
Because you use enable_if
without using the template parameter T
in your function templates. If you want to specialize for when the struct S
has a certain template parameter value N
, you'll need to use class template specialization.
因为您在函数模板中使用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>
{
....
};
回答by foxfireee
Well, I am not sure what you wanted to do, but maybe this code will help:
好吧,我不确定你想做什么,但也许这段代码会有所帮助:
#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);
}
This prints 1 and 2.
这将打印 1 和 2。
回答by Paul Fultz II
Use a default boolean template parameter, like this:
使用默认的布尔模板参数,如下所示:
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;};
};
回答by Anthony
To get std::enable_if
to work like this, you are relying on SFINAE. Unfortunately, at the point where you declare
要std::enable_if
像这样开始工作,您需要依赖 SFINAE。不幸的是,在您声明时
S<1> s1;
it will instantiate all of S<1>
's member declarations. SFINAE will only come into play at this point if S<1>
were an ill-formed construct. It is not. Unfortunately, it contains a function which is invalid, thus the instantiation of S<>
is invalid.
它将实例化所有S<1>
的成员声明。如果 SFINAES<1>
是一个格式错误的结构,那么此时它只会发挥作用。它不是。不幸的是,它包含一个无效的函数,因此实例化S<>
是无效的。
For things like this, I might defer to a seperate template struct:
对于这样的事情,我可能会遵循一个单独的模板结构:
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); }
};
回答by Jan Herrmann
For this case you could think about not using enable_if at all. It is posible to simply specialise f:
对于这种情况,您可以考虑根本不使用 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);
}