如何为模板化类型专门化/重载模板函数

时间:2017-02-17 23:24:05

标签: c++ templates c++14 template-specialization partial-specialization

我有以下课程:

template <class... T>
class thing {};

template <class T>
class container {
    public:
        container() {
            std::cout << "normal constructor" << std::endl;
        }
};

我可以用这种方式为container<int>的构造函数编写一个完整的特化:

template <>
container<int>::container() {
    std::cout << "int constructor" << std::endl;
}

我希望能够为container<thing<T>>定义一个类似的构造函数。我认为我试图写的是模板函数的部分特化(这是非法的。)这是我正在尝试的:

template <class T>
container<thing<T>>::container() {

}

这不会编译。

我不完全确定解决这个问题的正确方法是什么,模板类函数的重载和特化之间的界限越来越模糊。这可以简单地解决,还是需要type_traits(std::enable_if)?我该如何解决这个问题?

2 个答案:

答案 0 :(得分:7)

你不能部分专门化构造函数,但你没有必要部分专门化完整的类。

  

这可以简单地解决,还是需要type_traits / enable_if?我该如何解决这个问题?

委托构造函数和标记调度可以解决限制 它遵循一个最小的工作示例:

#include<iostream>

template <class... T>
class thing {};

template <class T>
class container {
    template<typename>
    struct tag {};

    template<typename U>
    container(int, tag<thing<U>>) {
        std::cout << "thing<U>" << std::endl;
    }

    container(char, tag<T>) {
        std::cout << "normal constructor" << std::endl;
    }

public:
    container(): container(0, tag<T>{}) {}
};

int main() {
    container<int> c1;
    container<thing<int>> c2{};
}

wandbox上查看。

请注意,如果您希望有两个以上的委托构造函数可以从中选择正确的构造函数,则可以轻松扩展它。
举个例子:

#include<iostream>

template <class... T>
class thing {};

template<typename> struct tag {};
template<int N> struct prio: prio<N-1> {};
template<> struct prio<0> {};

template <class T>
class container {    
    template<typename U>
    container(prio<2>, tag<thing<U>>) {
        std::cout << "thing<U>" << std::endl;
    }

    container(prio<1>, tag<double>) {
        std::cout << "double" << std::endl;
    }

    container(prio<0>, tag<T>) {
        std::cout << "normal constructor" << std::endl;
    }

public:
    container(): container(prio<2>{}, tag<T>{}) {}
};

int main() {
    container<int> c1;
    container<double> c2;
    container<thing<int>> c3{};
}

wandbox上查看。

答案 1 :(得分:4)

你不能部分专门化构造函数,但你可以部分专门化完整的类

template <class T>
class container<thing<T>>
 {
   public: 
      container() { }
 };