【问题标题】:How can I write a variadic template class?如何编写可变参数模板类?
【发布时间】:2021-03-10 16:24:21
【问题描述】:

据我了解,可变参数函数是带有可变数量参数的函数。

现在我想将它应用到我希望构造函数成为可变参数的模板函数。我不知道这是否可能以及如何实现。因此,我的问题是: 可能吗? 我该怎么做?

这是我的非可变模板类。我希望能够有不同数量的占位符参数 T(所以要么只有 T1,要么 T1、T2 或者 T1 到 T5)。

template<typename T1, typename T2>
    class tXmlBase
    {
    public:
        tXmlBase(tXmlDoc* doc, T1 id1);
        tXmlBase(tXmlDoc* doc, T1 id1, T2 id2);

        virtual ~tXmlBase();
    protected:
        tXmlDoc* xml_doc;

        pugi::xml_node root_node;
        pugi::xml_node base_node;
        pugi::xml_node parent_node;

        T1 identifier1;
        T2 identifier2;

        int n_childs;
        int n_attr;

我已阅读此内容,但不知道如何将其翻译到我的班级:https://en.cppreference.com/w/cpp/language/parameter_pack

编辑:为了更清楚: 这样做的目的如下: 此类应处理存储在 xml 文件的特定节点内的信息。让我们假设以下 xml 文件结构:

<root>
    <node>
        <elem id="1">
            <low_level_info type="info" content="abc"/>
            <low_level_info type="info" content="xyz" />
        </elem>
        <elem id="2">
            ...
        </elem>
     <node>
     <node>
        ...
     </node>
</root>

因此,有些节点只是节点,仅通过在上一次出现同名节点(此处为“名称”)之后位于第二个位置来区分,而其他节点则通过一个或多个属性(id、内容、类型)来区分.

我希望我的班级能够处理我有不同的方法来区分这些节点。

【问题讨论】:

  • 您可以编写带有类模板参数的 T1 或/和 T2 的构造函数,但是 T3...5 对应于什么?新模板参数?
  • 是的,没错。事实上,我想创建一个类,根据我的 xml 文件模式可能需要构造函数,这些构造函数在实例化它时需要使用变量属性值来识别正确的节点。我将编辑我的问题以使其更清楚。

标签: c++ variadic-templates variadic


【解决方案1】:

由于无法创建可变数据成员,因此您必须使用std::tuple。剩下的就很简单了:

template<typename... Ts>
class tXmlBase
{
public:
    tXmlBase(tXmlDoc* doc, Ts const&... id1);

    // if you have no other virtual member, it's better to remove this.
    virtual ~tXmlBase();
protected:
    tXmlDoc* xml_doc;

    pugi::xml_node root_node;
    pugi::xml_node base_node;
    pugi::xml_node parent_node;

    std::tuple<Ts...> identifiers;

    int n_childs;
    int n_attr;
};

如果您想对所有标识符做某事,您可以使用可变参数 lambda 和 std::apply

std::apply(
    [](auto&... id) {
        // expands into (id1.something(), id2.something(), ...)
        (id.something(), ...);
    },
    identifiers
);

【讨论】:

  • 哇,这看起来像专家级编程。我会看看这个。非常感谢,纪尧姆!
  • 语法起初令人生畏,但一旦你了解了可变参数扩展的工作原理,它就非常简单了
  • @ManyQuestions 请注意,我的第二个示例使用 C++17 功能。在 C++14 中进行模拟比较困难,但可能。
  • 分析器的第二部分是否意味着生成了一个数组,其中包含各个 something() 函数的返回值?如果我想让第一个代码部分与第二个代码部分一起使用,我是否应该始终对两个部分使用id,而不是在上部使用id1,在下部使用id?抱歉这么多问题 - 我是 C++ 初学者。
  • @ManyQuestions 没有构造数组。我只是使用逗号运算符来删除结果。如果你想把它们放在一个数组中,只需auto results = std::array{id.something()...}
猜你喜欢
  • 2016-12-11
  • 1970-01-01
  • 2015-05-06
  • 1970-01-01
  • 1970-01-01
  • 2020-07-08
  • 1970-01-01
  • 2016-12-01
  • 2021-10-01
相关资源
最近更新 更多