结构完全相同的专业化

时间:2015-03-13 01:55:27

标签: c++ templates specialization

考虑以下两个部分专业:

#include <iostream>
#include <vector>
#include <type_traits>

template <typename, typename...> struct A;

template <typename... Ts>
struct A<int, Ts...> {
    void foo (int a) const {std::cout << a << '\n';}
    void operator()(const std::vector<int>& v) const {std::cout << v.size() << '\n';}
};

template <typename... Ts>
struct A<char, Ts...> {
    void foo (char a) const {std::cout << a << '\n';}
    void operator()(const std::vector<char>& v) const {std::cout << v.size() << '\n';}
};

int main() {
    A<int, long, double> a;
    A<char, float, bool, short> b;
    a.foo(5);  // 5
    b.foo('!');  // !
    a({1,2,3});  // 3
    b({1,2,3});  // 3
}

如何只编写两次专精?

template <typename T, typename... Ts>
struct A<T, Ts...> {
    static_assert (std::is_same<T,int>::value || std::is_same<T,char>::value, "Error");
    void foo (T a) const {std::cout << a << '\n';}
    void operator()(const std::vector<T>& v) const {std::cout << v.size() << '\n';}
};

不起作用,因为它没有专门化任何东西,我不能将class = std::enable_if<std::is_same<T,int>::value || std::is_same<T,char>::value, T>::type放在任何地方,因为默认参数不能在一个包之后。上述特化仅适用于int和char。任何其他类型都将为该类提供其他一般定义。

2 个答案:

答案 0 :(得分:1)

谢谢T.C.,一如既往:

#include <iostream>
#include <vector>
#include <type_traits>

template <typename, typename...> struct A;

template <typename T, typename... Ts>
struct B {
    void foo (T a) const {std::cout << a << '\n';}
    void operator()(const std::vector<T>& v) const {std::cout << v.size() << '\n';}
};

template <typename... Ts>
struct A<int, Ts...> : B<int, Ts...> {};

template <typename... Ts>
struct A<char, Ts...> : B<char, Ts...> {};


int main() {
    A<int, long, double> a;
    A<char, float, bool, short> b;
    a.foo(5);  // 5
    b.foo('!');  // !
    a({1,2,3});  // 3
    b({1,2,3});  // 3
}

答案 1 :(得分:1)

我认为这更好。

template <typename T> struct B
{
    void foo (T a) const
    {
        std::cout << a << '\n';
    }
    void operator()(const std::vector<T>& v) const
    {
        std::cout << v.size() << '\n';
    }

};

template <typename T, typename... Ts>
struct A {};

template <typename... Ts>
struct A<int,Ts...> :public B<int>
    {};
template <typename... Ts>
struct A<char,Ts...> :public B<char>
    {};


int main()
{
    A<int, long, double> a;
    A<char, float, bool, short> b;
    a.foo(5);  // 5
    b.foo('!');  // !
    a( {1,2,3}); // 3
    b( {1,2,3}); // 3
}

这种方式更简单,更干净。