模板部分特化用于多种类型覆盖成员函数

时间:2016-06-29 11:34:29

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

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

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;
};

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

1 个答案:

答案 0 :(得分:0)

这是一个人为的例子,有点难以理解。但是,通过基本更改,您可以轻松添加所需内容。首先要注意的是,您在上面定义的内容不是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;
}