2

I'm (re)designing an API for this library. and there's this function which will take any number of arguments, templated. I can define it to be:

template<typename... Ts>    
void foo(bar_t bar, Ts... params);

or, alternatively, to be:

template<typename... Ts>    
void foo(bar_t bar, std::tuple<Ts...> params);

I know these two are interchangeable (in both directions):

C++11: I can go from multiple args to tuple, but can I go from tuple to multiple args?

so both options are just as general, but - should I prefer one variant over the other, or is it only a matter of taste / personal style?

Community
  • 1
  • 1
einpoklum
  • 118,144
  • 57
  • 340
  • 684
  • 1
    I would say that until an heterogeous initializer list `{t1, t2, t3, ...}` can be passed for `std::tuple`'s type *deduction* of `T1, T2...` (not part of the language now), the first option is still more general (but inconvenient for other reasons). They way the current language is, the second option *forces* the caller to know about an explicit `std::tuple<...>` or a `std::make_tuple` function. – alfC Apr 11 '17 at 20:24

1 Answers1

1
  1. The tuple method is harder on the caller side. Forwarding, for example, requires the user to use a different tuple definition or forward_as_tuple. By contrast, forwarding for the variadic case is a matter of your function's interface, nothing more. The caller doesn't even have to be aware of it.

  2. The tuple method is harder on the implementer's side for many uses. Unpacking a parameter pack is much easier than unpacking a tuple. And while parameter packs are limited, they're much more flexible out of the box than a tuple.

  3. The tuple method allows call chaining. There's no such thing as a variadic return value, and while structured binding comes close, you can't shove multiple return values into multiple parameters of a function. By contrast, with tuples and tuple return values, you can chain calls from one function to another.

So if call chaining is something that's likely to matter a lot to you, then a tuple interface might be appropriate. Otherwise, it's just a lot of baggage for little real gain.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982