刚刚用 SFINAE 选择函数模板的时候,就有了封装std::enable_if
成这样一个结构体的绝妙想法
template<typename T, typename U>
struct EnableWhenEqual
{
typedef typename std::enable_if<std::is_same<T, U>::value>::type type;
};
然后使用它,例如,像这样
template<typename T, typename U, typename Enable = EnableWhenEqual<T,U>::type >
void foo(T&& t, U&& u)
{
if (std::is_same<T,U>::value)
std::cout << "OK, overload allowed." << std::endl;
else
std::cout << "Bad. Should not compile!" << std::endl;
}
但是,这不起作用,正如人们通过调用所看到的那样
foo(1,1); //prints "OK, overload allowed"
foo(1,2.0); //prints "Bad, should not compile", but obviously does
另一方面,通过尝试创建
EnableWhenEqual<int,int>(); //compiles
EnableWhenEqual<int,double>(); //does not compile because type does not exist
获得编译器错误(“类型不是 std::enable_if 的成员”)。
这种行为的原因是什么?我问是因为根据我对 SFINAE 的一点了解,我会认为类型推导中的错误会导致排除重载......?
为了完整起见,可以使用模板别名来解决上述问题
template <typename T, typename U>
using EnableWhenEqual = typename std::enable_if<std::is_same<T,U>::value>::type;
是否还有使用结构而不是模板别名的替代方法?
编辑:这里我的意思是解决一般问题的实现。例如,这里
template<typename T, typename U, bool B, typename C=void>
struct EnableWhenEqual {};
template<typename T, typename U, typename C>
struct EnableWhenEqual<T,U,std::is_same<T,U>::value>
{
typedef typename C type;
};
对我不起作用,因为部分专业化需要一个简单的标识符。如果可以,可以用std::is_same
通用结构代替Condition<T,U>
。有什么选择吗?