【问题标题】:How can I specialize/overload a template function for a templated type如何专门化/重载模板化类型的模板函数
【发布时间】:2017-02-17 23:24:04
【问题描述】:

我有以下课程:

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

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

我可以用这种方式为container&lt;int&gt;的构造函数写一个完整的特化:

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

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

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

}

这不会编译。

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

【问题讨论】:

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


    【解决方案1】:

    您不能对构造函数进行部分特化,但不必对整个类进行部分特化。

    这可以简单解决还是需要 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 上查看。

    【讨论】:

    • 非常优雅的解决方案(恕我直言)
    • @max66 谢谢。整个类的部分专业化会很快导致代码重复,我通常会尽量避免。
    • @max66 添加了更多细节,以防有多个 specialized 构造函数。我希望你也喜欢它。 ;-)
    • 是的:rank类型的技巧;我没想过将它与委托构造函数结合使用。不错。
    【解决方案2】:

    你不能部分特化构造函数,但你可以部分特化整个类

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

    【讨论】:

    • 这样我将不得不完全(重新)定义类,对吗?
    • @user2079802 - 是的;但是,如果您必须(重新)定义的类的部分很小,与完整类相比,您可以创建一个小基类,只包含要定义/重新定义的部分。
    • @user2079802 - 也看看 skypjack 的解决方案:不要部分专门化构造函数,但是结合标签调度和委托构造函数,可以在不重新定义完整类的情况下解决问题
    猜你喜欢
    • 1970-01-01
    • 2014-10-01
    • 1970-01-01
    • 2016-07-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多