Search code examples
c++11variadic-templatesstdvectorindex-sequence

Expand std::vector into parameter pack


I have methods with the following signature:

void DoStuff(int i);
void DoStuff(int i, k);
void DoStuff(int i, int k, int l);

I have a method from where I would like to call the DoStuff methods as follows:

void CallDoStuff(const std::vector<int>& vElements) {
  // What magic is supposed to happen here to make vElements an expandable pack?
  DoStuff(vElemets...);
}

Is there any chance to achieve this? Is using std::index_sequence the right way? If yes, could you please provide me a simple example how to apply this to my problem?


Solution

  • It's possible, as long as you provide an upper bound to the number of arguments.

    Using Xeo's implementation of std::index_sequence for C++11:

    template <unsigned... Idx>
    void trampoline(const std::vector<int>& vElements, seq<Idx...>) {
        return DoStuff(vElements[Idx]...);
    }
    
    template <std::size_t Arity>
    void trampoline(const std::vector<int>& vElements) {
        return trampoline(vElements, typename gen_seq<Arity>::seq{});
    }
    
    template <unsigned... Idx>
    void CallDoStuff(const std::vector<int>& vElements, seq<Idx...>) {
        using trampoline_t = void (*)(const std::vector<int>&);
        constexpr trampoline_t trampolines[]{
            trampoline<Idx>...
        };
        trampolines[vElements.size()](vElements);
    }
    
    template <std::size_t Max>
    void CallDoStuff(const std::vector<int>& vElements) {
        assert(vElements.size() <= Max);
        return CallDoStuff(vElements, typename gen_seq<Max + 1>::seq{});
    }
    

    See it live on Wandbox