2

I have a helper function f that receives a variadic number of tuple-like arguments, but I'd be okay restricting it to std::tuple. These are in practice always temporaries, so a typical call looks something like this:

int i{};
f(
  std::tuple{"hello",2},
  std::tuple{"world","!",3},
  std::tie  ("!",i)
//^^^^^^^^^^
);

The function template looks (simplified) something like this:

template <typename... T>
void f(T&&... t) {
  // do stuff with t...
}

Problem

The issue I have with this is that I want to remove the need for the caller to restate that each argument is a tuple because it is redundant --- so I want a call of the form:

// goal
f(
  {"hello",2},
  {"world","!",3},
  {"!",std::ref(i)}
);

Unfortunately, deducing this type appears to be impossible, even if I contract f down to accepting only something like template <Tuple... T> where Tuple only admits types like std::tuple<Args...>.

Some attempts

The only type that can somewhat deduce its nested template arguments is std::initializer_list as in:

template <typename... T>
void g(std::initializer_list<T>...) {}

// call:
g({1,2}, {"hello","world","!"}); // fine

Alas, that supports only homogeneous values in each argument, whereas f's arguments are composed of heterogeneous values (e.g. char const* and int). To my understanding this works because std::initializer_list is magic in that it has language support. So, we probably cannot recreate that behaviour on a different type.

I even briefly considered making each argument a tuple of std::any but the individual arguments may have a different number of values.

Question

Is there a way to achieve a call as shown in the code snippet labelled "goal"? It would be okay if I have to write my own argument type instead of using std::tuple, although I don't see how that would help.

bitmask
  • 32,434
  • 14
  • 99
  • 159
  • What C++ standard are you using? 14, 17? – alagner Mar 23 '23 at 09:35
  • 1
    Is that supposed to be 100% generic, or is there a set of tuples to be supported? Tuple's inside types cannot be deduced as explained [here](https://stackoverflow.com/a/50031255/4885321) but I wonder if a workaround could be provided, eg. a non-generic tuple with variants and optionals inside it. – alagner Mar 23 '23 at 10:06
  • @alagner Not a 100% generic, but the number of possible combinations of types is rather large. I have done some experiments with throwing some combinations into a variant and passing a concrete type. However, the main problem there is that the number of arguments (i.e. tuples) is completely arbitrary. Some calls have 2 some have 10. So this would require to provide a large number of overloads (`f()`, `f(H)`, `f(H,H)`, `f(H,H,H)`, ...) and hope nobody ever needs to pass more functions than there are overloads. Not great. – bitmask Mar 23 '23 at 10:18
  • Do you really want a solution that doesn't use the tuple keyword? The effort to develop such a solution seems to be more than typing std::tuple multiple times. Although I did try to think of a solution like using some kind of deduction guide, but doesn't seem to be working. – kiner_shah Mar 23 '23 at 10:38
  • Don't know why my comment that this is C++20 was deleted. Weird. – bitmask Mar 23 '23 at 10:40

0 Answers0