我有一个模板化的类,我想根据模板参数启用不同的构造函数。具体来说,我想使用std::is_compound
作为标准。
// bla.cpp
#include <type_traits>
#include <vector>
template <typename T>
class Foo{
double bar;
public:
template<typename U=T,
class = typename std::enable_if<std::is_compound<U>::value>::type
>
Foo(typename T::value_type& b):bar(b){}
template<typename U=T,
class = typename std::enable_if<!std::is_compound<U>::value>::type
>
Foo(T b):bar(b){}
};
int main(){
double d=1.0;
Foo<std::vector<double>> f2(d); // works
Foo<double> f1(d); // compiler error
}
我收到以下编译错误:
g ++ -std = gnu ++ 11 bla.cpp
bla.cpp: In instantiation of ‘class
Foo<double>’: bla.cpp:22:18: required from here bla.cpp:11:2: error:
‘double’ is not a class, struct, or union type
问题似乎是正在使用构造函数的第一个版本,但由于double::value_type
不存在而失败。问题是该构造函数不应该首先位于Foo<double>
,因为std::is_compound<double>::value
是false
。
为什么std::enable_if
似乎无法正常工作?
答案 0 :(得分:5)
在typename T::value_type&
中,T
无法替换为double
。由于T
是类模板的模板参数而不是构造函数模板的模板参数,因此您无法通过替换失败来排除过载。 SFINAE仅在涉及相关模板的参数时才有效。
如果您使用typename U::value_type&
,则会发现替换失败并非错误,因为U
是构造函数模板的参数,而不是类模板的参数。