enable_if:没有参数的void成员函数的最小示例

时间:2017-01-16 00:28:02

标签: c++ c++11 void sfinae enable-if

我正在尝试更好地理解C ++ 11中的std::enable_if,并且一直在尝试编写一个最小的示例:具有成员函数A的类void foo()基于类模板中T类型的不同实现 下面的代码给出了期望的结果,但我还没有完全理解它。为什么版本V2有效,而V1无效?为什么"多余"是否需要输入U

#include <iostream>
#include <type_traits>

template <typename T>
class A {

    public:

        A(T x) : a_(x) {}

        // Enable this function if T == int
        /* V1 */ // template <           typename std::enable_if<std::is_same<T,int>::value,int>::type = 0>
        /* V2 */ template <typename U=T, typename std::enable_if<std::is_same<U,int>::value,int>::type = 0>
        void foo() { std::cout << "\nINT: " << a_ << "\n"; }

        // Enable this function if T == double
        template <typename U=T, typename std::enable_if<std::is_same<U,double>::value,int>::type = 0>
        void foo() { std::cout << "\nDOUBLE: " << a_ << "\n"; }

    private:

        T a_;

};

int main() {
    A<int> aInt(1); aInt.foo();
    A<double> aDouble(3.14); aDouble.foo();
    return 0;
}

是否有更好的方法来实现所需的结果,即基于类模板参数实现void foo()函数的不同实现?

2 个答案:

答案 0 :(得分:2)

我知道这不会完全回答你的问题,但它可能会给你更多的想法和理解你如何使用std::enable_if

您可以使用以下内容替换您的foo成员函数,并具有相同的功能:

template<typename U=T> typename std::enable_if<std::is_same<U,int>::value>::type
foo(){ /* enabled when T is type int */ }

template<typename U=T> typename std::enable_if<std::is_same<U,double>::value>::type
foo(){ /* enabled when T is type double */ }

前段时间我对enable_if的工作方式有了很好的理解,但遗憾的是我已经忘记了它的大部分复杂性,只记得使用它的更实用的方法。

答案 1 :(得分:0)

关于第一个问题:为什么V1不起作用? SFINAE仅适用于重载分辨率 - 但是在实例化类型A的位置会导致错误,远在foo()重载解析之前。

我想有很多可能的实现 - 最合适的取决于实际的案例。一种常见的方法是将不同模板类型的A部分推迟到辅助类。

template <typename T>
class A_Helper;

template <>
class A_Helper<int> {
public:
    static void foo( int value ){
        std::cout << "INT: " << value << std::endl;
    }
};

template <>
class A_Helper<double> {
public:
    static void foo( double value ){
        std::cout << "DOUBLE: " << value << std::endl;
    }
};

template <typename T>
class A {
public:

    A( T a ) : a_(a) 
    {}

    void foo(){
        A_Helper<T>::foo(a_);
    }

private:
    T a_;
};

A的其余部分只能以通用方式声明一次 - 只有不同的部分才会被推迟到帮助程序。根据您的要求,有很多可能的变化......