C ++:尝试在类中封装std :: enable_if

时间:2014-09-02 18:40:27

标签: c++ c++11 sfinae template-aliases

当我有一个光荣的想法将std::enable_if封装在像这样的结构中时,我只是使用SFINAE来选择函数模板

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

获得编译器错误(“type不是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>。任何替代方案?

2 个答案:

答案 0 :(得分:5)

这应该可以解决问题:

template<typename T, typename U>
struct EnableWhenEqual : std::enable_if<std::is_same<T, U>::value>
{
};

http://coliru.stacked-crooked.com/a/650202ba3d42d34b

答案 1 :(得分:2)

另一种封装:

template<class T, class U>
using EnableWhenEqual_t = typename std::enable_if< std::is_same<T,U>::value >::type;

template<typename T, typename U, typename Enable = EnableWhenEqual_t<T,U> >
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;
}

注意当您询问有关模板VS处理的问题时,请提供完整的Visual Studio版本。 VS模板支持非常古怪。