24

Here's a variadic template function that I've written:

template<class Container, class Value, class... Args>
Value& insert(Container& c, Args&&... args) {
    c.emplace_back(args);
    return c.back();
}

When I use insert like this I'm getting an error:

list<int> lst;
int& num = insert<list<int>, int, int>(lst, 4);

The error complains about this line in the body of insert:

c.emplace_back(args); // <= 'args' : parameter pack must be
                      //             expanded in this context

What does that mean and how can I fix it?

reuben
  • 3,360
  • 23
  • 28
  • 8
    You forgot ellipsis: `c.emplace_back(args...);`. – Constructor Dec 14 '13 at 21:02
  • 2
    `Value` should also be the first template argument so that template-argument deduction can be used for the other arguments (i.e `insert(lst, 4);`) – David G Dec 14 '13 at 21:04
  • 1
    And you forgot to forward: `c.emplace_back(std::forward(args)...);` – dyp Dec 14 '13 at 21:08
  • A container is required to have a member `value_type`, you can use it to get rid of the `Value` template parameter: `template typename Container::value_type& insert(Container& c, Args&&... args); insert(lst, 4);` – dyp Dec 14 '13 at 21:10

1 Answers1

38

The error is due to the missing ellipsis (...) after args when passing all individual parameters (rather than the parameter pack) to emplace_back.

The fixed (and improved) version:

template<class Container, class... Args>
auto insert(Container& c, Args&&... args) -> decltype (c.back()) {
    c.emplace_back(std::forward<Args>(args)...);
    return c.back();
}
Florian Winter
  • 4,750
  • 1
  • 44
  • 69
Jarod42
  • 203,559
  • 14
  • 181
  • 302