是否可以使用std :: enable_if选择成员模板专业化

Is it possible to use std::enable_if to select a member template specialization?

本文关键字:成员 选择 专业化 if 可以使 std enable 是否      更新时间:2023-10-16

给定类声明

class A {
    template <typename T> T foo();
};

我想专门针对T的各种类型(int,...)和类型类(POD,非POD)的A::foo。不幸的是,我似乎无法将std::enable_if用于后者。以下没有编译:

template <> int A::foo<int>(); // OK
template <typename T> 
typename std::enable_if<is_pod<T>::value, T>::type foo(); // <<<< NOT OK!
template <typename T> 
typename std::enable_if<!is_pod<T>::value, T>::type foo(); // <<<< NOT OK!

问题可能是由于std::enable_if<...>的内容是功能签名的一部分,并且我没有在A中声明任何此类成员。那么如何根据类型特征专业化模板成员?

我没有理由在这里专业,超载该功能在我的脑海中似乎就足够了。

struct A
{
    template <typename T>
    typename std::enable_if<std::is_integral<T>::value, T>::type foo()
    {
        std::cout << "integral" << std::endl;
        return T();
    }
    template <typename T>
    typename std::enable_if<!std::is_integral<T>::value, T>::type foo()
    {
        std::cout << "not integral" << std::endl;
        return T();
    }
}

检查POD或没有POD时,您只有这两种选择,因此不需要更通用的功能(并且不允许,因为这是模棱两可的)。您还需要更多吗?您可以在std::enable_if<std::is_same<int, T>::value, T>::type的帮助下检查不专业的明确类型。

我只是将其转发到一个结构,该结构确实可以很好地处理:

#include <type_traits>
#include <iostream>
template <typename T, typename = void>
struct FooCaller;
class A {
public:
    template <typename T>
    T foo() {
        // Forward the call to a structure, let the structure choose 
        //  the specialization.
        return FooCaller<T>::call(*this);
    }
};
// Specialize for PODs.
template <typename T>
struct FooCaller<T, typename std::enable_if<std::is_pod<T>::value>::type> {
    static T call(A& self) {
        std::cout << "pod." << std::endl;
        return T();
    }
};
// Specialize for non-PODs.    
template <typename T>
struct FooCaller<T, typename std::enable_if<!std::is_pod<T>::value>::type> {
    static T call(A& self) {
        std::cout << "non-pod." << std::endl;
        return T();
    }
};
// Specialize for 'int'.
template <>
struct FooCaller<int> {
    static int call(A& self) {
        std::cout << "int." << std::endl;
        return 0;
    }
};