Search code examples
c++c++11boost-mpl

Generate a std::tuple from standard container


Is there a portable way to generate a std::tuple (really a std::array) from the contents of a container? Such a tuple would allow std::apply to extract function arguments from a container.

My first attempt, using tail recursion, fails with compiler error: "recursive template instantiation exceeds maximum...".

I could not quite get my second attempt (std::for_each with a mutable lambda holding tuple) to compile with desired results.

I assume that something along the lines of how boost::mpl handles variadic metafunctions (ie magic using boost::preprocessor) could be made to work -- but that's so c++03. I'm hoping there's a better solution.

The function signature would look something like:

std::list<int> args_as_list = {1, 2, 3, 4};
auto tpl = args_as_tuple(args_as_list);

where type of tpl is std::array<int const, 4>.


Solution

  • Short answer: no, it is not possible.

    Explanation: both std::tuple and std::array require compile-time information about number of elements. std::list or std::vector can provide only runtime information about elements count.

    your args_as_tuple function would have to be a template, taking number of expected arguments as template argument (args_as_tuple<4>(args_as_list)).

    Although having to put number of arguments as template argument seems harsh, but in case of your example it's is quite obvious - number of function arguments (function provided to std::apply) has to be known on compile-time as well.
    For more generic code you could use: function-traits or code from this answer.
    Or use std::array from begging instead of std::list (a lot of generic template code, but good compile time checks)