ManyQuestions
ManyQuestions

Reputation: 158

How can I write a variadic template class?

To my understanding variadic functions are functions that take a variable number of arguments.

Now I would like to apply this to a template function for which I want the constructor to be a variadic one. I don't know if this is possible and how I can accomplish this. My questions are therefore: Is it possible? And how can I do that?

Here is my non-variadic template class. I want to be able to have varying number of placeholder parameters T (so either T1 only, or T1, T2 or maybe T1 to 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;

I've read this but I am not sure how to translate this to my class: https://en.cppreference.com/w/cpp/language/parameter_pack

EDIT: For better clarity: The purpose of this is following: This class shall handle the information stored inside a specific node of a xml-file. Let's assume following xml-file structure:

<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>

So some nodes are just nodes and differentiated only by being on the second position after the previous occurance of the node of same name (here "name"), others are differentiated by one or more attributes (id, content, type).

And I'd like my class to be capable to handle that I have different ways to differentiate these nodes.

Upvotes: 0

Views: 993

Answers (1)

Guillaume Racicot
Guillaume Racicot

Reputation: 41770

Since there is no way to create a variadic data member, you'll have to use a std::tuple. The rest is pretty straightforward:

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;
};

If you want to do something for all identifiers, you can use a variadic lambda and std::apply:

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

Upvotes: 3

Related Questions