3

I have a template variadic function:

template <typename ... argsType>
static bool Call(std::string const& Key, argsType&& ... Args)
{
    /* ... */
}

This is called for example like this:

Call("add2", 1, 2);
Call("add3", 1, 2, 3);
Call("true", true);

Then I also have different containers with a variable number of elements:

std::vector<int> v1 = {1, 2};
std::vector<int> v2 = {1, 2, 3};
std::vector<bool> v3 = {true};

Now is there any way to call the variadic function with the values of these containers, or do I have to change that function so that it accepts containers as parameter? If possible I would like to do something like this:

Call("add2", /* use v1 here */);
Call("add3", /* use v2 here */);
Call("true", /* use v3 here */);
Rakete1111
  • 47,013
  • 16
  • 123
  • 162
Matthias
  • 9,817
  • 14
  • 66
  • 125
  • 3
    The size of the container isn't known at compile time, so not really. You could write an overload which expects a container and have the variadic version construct a container from the parameter pack and forward it to the container overload. Is that a reasonable solution for you? – TartanLlama Dec 15 '16 at 15:51
  • @TartanLlama Well, that would be my plan B. But I am/was hoping there is a better solution without that overload. – Matthias Dec 15 '16 at 15:54
  • 2
    I voted to re-open as the question marked as a duplicate has a known number of arguments to extract from the vector, which isn't the case here and makes answers very different. – TartanLlama Dec 15 '16 at 15:54
  • @TartanLlama Could you please still provide the link to that other question? Maybe it could help me in my case as well. Thanks! – Matthias Dec 15 '16 at 15:55
  • http://stackoverflow.com/questions/23946300/expanding-an-stl-container-into-a-variadic-template?noredirect=1&lq=1 – TartanLlama Dec 15 '16 at 15:58
  • Sorry about that @TartanLlama. I didn't realize you needed the function signature at compile time on the dupe I used. Should have read it more thoroughly. – NathanOliver Dec 15 '16 at 16:07
  • Listing the underlying problem is often useful. As a guess, you are doing some kind of scripting hooks? – Yakk - Adam Nevraumont Dec 15 '16 at 16:37
  • @Yakk Yes indeed, that was a good guess :) – Matthias Dec 15 '16 at 18:06
  • @Matthias This is the wrong way to do a scripting hook usually. I cannot tell you the right way without details of what your scripting API looks like. – Yakk - Adam Nevraumont Dec 15 '16 at 18:17

1 Answers1

3

No, you cannot. The number of elements in a vector is a runtime quantity, and the number of arguments passed to a function is a compile-time quantity. The only way to unpack a vector into a function like that is through something like a giant switch statement:

switch (v.size()) {
case 0: Call("add2"); break;
case 1: Call("add2", v[0]); break;
case 2: Call("add2", v[0], v[1]); break;
// ...
}

which can be generated with the help of index_sequence but only if you know what the limit of v.size() actually is.

What you would typically do instead is just pass in a pair of iterators:

template <class Iter>
static bool Call(std::string const& Key, Iter first, Iter last);

Call("add2", v.begin(), v.end());

Or collapse that into something like gsl::span:

template <class T>
static bool Call(std::string const& Key, gsl::span<T> values);

Call("add2", gsl::span<int>{v});
Barry
  • 286,269
  • 29
  • 621
  • 977