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

enable_if: minimal example for void member function with no arguments

我试图更好地理解 C++11 中的 std::enable_if,并且一直在尝试编写一个最小的示例:带有成员函数 class A void foo() 根据 class 模板中的类型 T 具有不同的实现。
下面的代码给出了期望的结果,但我还没有完全理解它。为什么版本 V2 有效,但 V1 无效?为什么需要 "redundant" 类型 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;
}

是否有更好的方法来实现预期的结果,即根据 class 模板参数对 void foo() 函数进行不同的实现?

关于第一个问题:为什么V1不行? SFINAE 仅适用于重载决议 - 然而,V1 在类型 A 被实例化时导致错误,远早于 foo() 重载决议。

我想有很多可能的实现方式——哪一种最合适取决于所讨论的实际情况。一种常见的方法是将 A 中对于不同模板类型不同的部分推迟到助手 class.

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 的其余部分只能以通用方式声明一次 - 只有不同的部分才会延迟到助手。有很多可能的变化 - 取决于您的要求...

我知道这不会完全回答你的问题,但它可能会给你更多的想法和理解如何使用 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 的工作原理有了很好的理解,但遗憾的是我忘记了它的大部分复杂之处,只记得更实用的使用方法。