2017-02-17 83 views
2

我有以下类别:我如何专注/重载一个模板函数的模板类型

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)?我该如何解决这个问题?

回答

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

非常优雅的解决方案(恕我直言) – max66

+0

@ max66谢谢。整个班级的部分专业化很快就会导致代码重复,如果可能的话,我通常会尽量避免它。 – skypjack

+0

@ max66仅在多个_specialized_构造函数的情况下添加更多细节。我希望你也喜欢它。 ;-) – skypjack

4

你不能偏专门的构造函数,但可以部分专业类的全

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

这样我就不得不完全(重新)定义类,对吗? – user2079802

+0

@ user2079802 - 是;但是,如果您需要(重新)定义的类的部分很小,与完整的类相比,您可以创建一个只包含要定义/重新定义的部分的基类。 – max66

+0

@ user2079802 - 更要看skypjack的解决方案:不偏专门的构造函数,但相结合的标签调度和委托的构造,就可以解决问题,而无需重新定义完整的类 – max66