多个类型覆盖成员函数的模板部分特化

Template partial specialization for multiple types overriding member function

本文关键字:板部 函数 类型 覆盖 成员      更新时间:2023-10-16

我有如下定义的类成员函数,为其中一个提供规范,让用户为其他的提供自己的规范:

template <typename T>
class Foo {
    // specialization provided for integral types
    template <typename Enable = T>
    typename std::enable_if<std::is_integral<Enable>::value, size_t>::type
        bar(const T& value);
    // provide your own specialization for other types
    template <typename Enable = T>
    typename std::enable_if<!std::is_integral<Enable>::value, size_t>::type
        bar(const T& value);
};
template <typename T>
template <typename Enable>
typename std::enable_if<std::is_integral<Enable>::value, size_t>::type
    Foo<T>::bar(const T& value) {
    ...
}

现在,我想为这个函数提供一个专门化,它将适用于整对类型。我有一个模板元函数检查整对定义如下:

template <typename T>
struct is_integral_pair : std::false_type {}; 
template <typename T1, typename T2> 
struct is_integral_pair<std::pair<T1, T2>> {
    static const bool value =
        std::is_integral<T1>::value && std::is_integral<T2>::value;
};

我是否有可能提供我自己的专门化,以便它适用于所有整数对,也许使用我上面定义的模板元函数?

这是一个有点做作的例子,有点难以理解。然而,通过一个基本的改变,很容易添加你需要的东西。首先要注意的是,你上面定义的不是bar的部分专门化(这是不可能的,因为你不能部分专门化一个函数),而是重载。接下来,您有一个人造的系统,其中您有一个与函数参数无关的Enable参数—这真的是您的意图吗?如果您将函数的模板参数更改为与其变量参数相同的类型,那么问题就变得简单了—您可以为整对添加另一个重载,再次使用SFINAE来帮助您。下面是一个实现你所需要的东西的例子:

#include <iostream>
template <typename T>
class Foo {
public:
    // specialization provided for integral types
    template <typename Enable>
    typename std::enable_if<std::is_integral<Enable>::value, size_t>::type
        bar(const Enable& value);
    // provide your own specialization for other types
    template <typename Enable>
    typename std::enable_if<!std::is_integral<Enable>::value, size_t>::type
        bar(const Enable& value);
    // provide your own specialization for integral pairs 
    template <typename U, typename V>
    typename std::enable_if<std::is_integral<U>::value && std::is_integral<V>::value, size_t>::type
        bar(const std::pair<U,V>& value);
};
template <typename T>
template <typename Enable>
typename std::enable_if<std::is_integral<Enable>::value, size_t>::type
    Foo<T>::bar(const Enable& value) 
{
    std::cout << "Integral" << std::endl;
    return 0;
}
template <typename T>
template <typename Enable>
typename std::enable_if<!std::is_integral<Enable>::value, size_t>::type
    Foo<T>::bar(const Enable& value) 
{
    std::cout << "Non-Integral" << std::endl;
    return 0;
}
template <typename T>
template <typename U, typename V>
typename std::enable_if<std::is_integral<U>::value && std::is_integral<V>::value, size_t>::type
    Foo<T>::bar(const std::pair<U,V>& value) 
{
    std::cout << "Integral pair" << std::endl;
    return 0;
}
int main()
{
    Foo<int> foo;
    foo.bar(1);              //output "Integral"
    foo.bar(1.0);            //output "Non-Integral"
    foo.bar(std::pair<float, int>(1.0, 1));    //output "Non-integral"
    foo.bar(std::pair<long, int>(1, 1));       //output "Integral pair"
    return 0;
}