Search code examples
c++c++11variadic-functions

Inserting a variadic argument list into a vector?


Forgive me if this has been answered already, as I couldn't find it...

Basically I have an object that needs to take a variadic argument list in it's constructor and store the arguments in a vector. How do I initialize a vector from a the arguments of a variadic constructor?

class GenericNode {
public:
    GenericNode(GenericNode*... inputs) {
            /* Something like... */
        // inputs_.push_back(inputs)...;
}
private:
    std::vector<GenericNode*> inputs_;
};

Solution

  • The best thing would be to use an initializer list

    #include <initializer_list>
    #include <vector>
    class GenericNode {
    public:
        GenericNode(std::initializer_list<GenericNode*> inputs) 
            :inputs_(inputs) {} //well that's easy
    private:
        std::vector<GenericNode*> inputs_;
    };
    int main() {
        GenericNode* ptr;
        GenericNode node{ptr, ptr, ptr, ptr};
    } //compilation at http://stacked-crooked.com/view?id=88ebac6a4490915fc4bc608765ba2b6c
    

    The closest to what you already have, using C++11 is to use the vector's initializer_list:

        template<class ...Ts>
        GenericNode(Ts... inputs) 
            :inputs_{inputs...} {} //well that's easy too
        //compilation at http://stacked-crooked.com/view?id=2f7514b33401c51d33677bbff358f8ae
    

    And here's a C++11 version with no initializer_lists at all. It's ugly, and complicated, and requires features missing from many compilers. Use the initializer list

    template<class T>
    using Alias = T;
    
    class GenericNode {
    public:
        template<class ...Ts>
        GenericNode(Ts... inputs) { //SFINAE might be appropriate
             using ptr = GenericNode*;
             Alias<char[]>{( //first part of magic unpacker
                 inputs_.push_back(ptr(inputs))
                 ,'0')...,'0'}; //second part of magic unpacker
        }
    private:
        std::vector<GenericNode*> inputs_;
    };
    int main() {
        GenericNode* ptr;
        GenericNode node(ptr, ptr, ptr, ptr);
    } //compilation at http://stacked-crooked.com/view?id=57c533692166fb222adf5f837891e1f9
    //thanks to R. Martinho Fernandes for helping me get it to compile
    

    Unrelated to everything, I don't know if those are owning pointers or not. If they are, use std::unique_ptr instead.