【问题标题】:Variable length template arguments list?可变长度模板参数列表?
【发布时间】:2009-10-02 20:03:51
【问题描述】:

我记得看到过这样的事情:

template <ListOfTypenames>
class X : public ListOfTypenames {};

也就是说,X 继承自作为模板参数传递的可变长度类型名列表。当然,这段代码是假设的。

不过,我找不到任何参考资料。是否可以?是 C++0x 吗?

【问题讨论】:

    标签: c++ templates c++11 variable-length


    【解决方案1】:

    你可以在当前的 C++ 中做到这一点。您为模板提供“足够大”数量的参数,并为它们提供默认值:

    class nothing1 {};
    class nothing2 {};
    class nothing3 {};
    
    template <class T1 = nothing1, class T2 = nothing2, class T3 = nothing3>
    class X : public T1, public T2, public T3 {};
    

    或者您可以变得更复杂并使用递归。首先你前向声明模板:

    class nothing {};
    
    template <class T1 = nothing, class T2 = nothing, class T3 = nothing>
    class X;
    

    然后你专门针对所有参数都是默认的情况:

    template <>
    class X<nothing, nothing, nothing> {};
    

    然后您正确定义通用模板(之前您只前向声明):

    template <class T1, class T2, class T3>
    class X : public T1, public X<T2, T3>
    

    注意在基类中,你继承了 X,但你错过了第一个参数。所以他们都沿着一个地方滑动。最终它们都将成为默认值,并且专门化将启动,它不会继承任何东西,从而终止递归。

    更新:只是有一种奇怪的感觉,我以前发布过类似的东西,and guess what...

    【讨论】:

    • 你也可以只使用一个“无”类
    • @sellibitze - 我在递归版本中只使用了一个“无”类。在非递归版本中,您不能对默认值使用相同的类,因为您会收到“没有什么已经是直接基类”错误。
    • 我不明白:为什么从X继承时跳过第一个参数?
    • 如果X&lt;T1, T2, T3&gt;继承X&lt;T1, T2, T3&gt;会发生什么?无限深度!但是跳过第一个参数,意味着我们继承了X&lt;T2, T3, nothing&gt;,后者又继承了X&lt;T3, nothing, nothing&gt;,后者又继承了X&lt;nothing, nothing, nothing&gt;。对于那种“一无所有”的情况,有一个不继承任何东西的专业化,所以它停止了。顺便说一句,在递归示例的最后一部分中,我最初没有使用T1,所以我添加了它的继承以使其与非递归示例一致(否则它实际上并没有回答问题!)
    • @Yousf - 很容易为非类类型修复它。在通用模板中,不是直接继承T1,而是继承W&lt;T1&gt;,其中W是一个包装类,可能带有一个typedef成员,让你得到类型参数。
    【解决方案2】:

    听起来您指的是 C++0x Variadic Templates。您也可以使用来自 Loki 的 Alexandrescu 的 TypeList 构造来实现相同的效果。

    我相信有问题的可变参数模板语法如下所示。

    template <typename...T>
    class X : public T... {};
    

    【讨论】:

    • 如果我没记错的话,你还需要解压类型:public T... {};
    【解决方案3】:

    正如其他人已经回答的那样,可变参数模板是下一个标准的一部分,但可以在当前的 C++ 中进行模拟。一种方便的工具是使用Boost.MPL 库。在您的代码中,您编写了一个模板参数(我们将其命名为“Typelist”),模板的用户将 typelist 包装在 MPL 序列中。示例:

    #include "YourType.h"
    #include "FooBarAndBaz.h"
    #include <boost/mpl/vector.hpp>
    
    YourType<boost::mpl::vector<Foo, Bar, Baz> > FooBarBaz;
    

    在“YourType”的实现中,可以通过各种元函数访问Typelist中的元素。例如,at_c&lt;Typelist, N&gt; 是列表的第 N 个元素。另一个例子,你问题中的“X”类可以用inherit_linearly写成:

    //Warning: Untested
    namespace bmpl = boost::mpl;
    template<class Typelist>
    class X : bmpl::inherit_linearly<Typelist, bmpl::inherit<bmpl::_1, bmpl::_2> >::type
    {
    ...
    };
    

    【讨论】:

      【解决方案4】:

      可变数量的模板是下一个 C++ 标准的一部分。但是,如果您使用 GCC(从 4.3 版开始),您可以体验一下。这是list of available C++0x features in GCC。您正在寻找可变参数模板。

      顺便说一句,如果你需要关于如何实现 Earwicker 描述的继承机制的正式参考,它在书 C++ Templates 上。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-04-21
        • 1970-01-01
        • 1970-01-01
        • 2016-12-01
        • 2020-06-05
        • 2018-11-19
        • 1970-01-01
        • 2011-11-27
        相关资源
        最近更新 更多