尝试通过enable_if

时间:2019-09-16 21:39:27

标签: c++ c++11 templates template-meta-programming sfinae

我只是在C ++中使用std::enable_if尝试SFINAE。我以为我理解了理论部分,直到无法获得下面的代码来编译。在Visual Studio和Linux上,不同的行为加剧了这种混乱。只要您不取消注释(Calculator<int> cInt;),就会在VS上编译此粘贴的代码。但是,使用GCC会给我编译错误。我已经在STL实现中看到了这种代码,我真的期望在任何地方都可以有更多标准化的实现。无论如何,您能否在这里检查并提出我的理解方面的空白?

template<typename T>
class Calculator
{
public:
    typename enable_if<is_arithmetic<T>::value, T>::type 
    addition(T a, T b)
    {
        return a + b;
    }
    typename enable_if<!is_arithmetic<T>::value, T>::type
    addition(T a, T b)
    {
        cout << "Default\n";
        return a;
    }
};

void SFINAE()
{
//  Calculator<int> cInt; 
}


int main ()
{
    SFINAE();
    return 0;
}

GCC 8.1错误日志: j

doodle.cpp:30:3: error: 'typename std::enable_if<(! std::is_arithmetic<_Tp>::value), T>::type Calculator<T>::addition(T, T)' cannot be overloaded with 'typename std::enable_if<std::is_arithmetic<_Tp>::value, T>::type Calculator<T>::addition(T, T)'
   addition(T a, T b)
   ^~~~~~~~
jdoodle.cpp:25:3: note: previous declaration 'typename std::enable_if<std::is_arithmetic<_Tp>::value, T>::type Calculator<T>::addition(T, T)'
   addition(T a, T b)

取消注释int计算器类初始化时,在VS上出现错误日志:

sfinae.h(17): error C3646: 'addition': unknown override specifier
sfinae.h(17): error C2059: syntax error: '('
sfinae.h(18): error C2334: unexpected token(s) preceding '{'; skipping apparent function body

1 个答案:

答案 0 :(得分:2)

在一个类中,SFINAE适用于 template 方法和该方法的模板参数。

所以

typename enable_if<is_arithmetic<T>::value, T>::type 
addition(T a, T b)
{
    return a + b;
}

不起作用,因为您试图将SFINAE应用于不是模板的方法,并且将测试(is_arithmetic<T>::value)应用于类的template参数。

您应该尝试

template <typename U = T>
typename enable_if<is_arithmetic<U>::value, T>::type 
addition(T a, T b)
{
    return a + b;
}

通过这种方式,模板成为带有模板参数(U)且带有 默认类型(T),并且您对该方法的模板参数进行了SFINAE测试。

与其他addition()方法相同。

为避免有人“劫持”您的代码,从而泄露了错误的模板参数

Calculator<std::string>  cs;

cs.add("a", "b");  // call the Default version
cs.template add<int>("a", "b"); // call the arithmetic version!!!

您可以强加UT是同一类型

template <typename U = T>
typename std::enable_if<std::is_arithmetic<U>::value
                     && std::is_same<T, U>::value, T>::type 
addition(T a, T b) //   ^^^^^^^^^^^^^^^^^^^^^^^^^
{
    return a + b;
}