Search code examples
c++templatesc++11metaprogrammingperfect-forwarding

Forward an element of a tuple


Consider the following code:

template <unsigned int Index, class Tuple, class Type = /* Something1 */>
Type forward(Tuple&& tuple)
{
    return /* Something2 */;
}

I would like to find what is the correct syntax of /* Something1 */ and /* Something2 */ in order to forward the element specified by Index of the input tuple. I know that other conceptions/syntax would be available, but in order to understand correctly how things work in such a context (consider this as an academic exercice), I would like an answer that satisfy the following conditions:

  • no overload for different cases: there will be only one templated function forward
  • no change except /* Something1 */ and /* Something2 */ (and maybe on the return type if it should be Type&& instead of Type)
  • metaprogramming crazyness, decltype and std::declval are accepted

For example, if Tuple = std::tuple<char, int, double>, then forward<2>(tuple) should forward the third element (if the tuple is passed as a const reference, then the function should return a const reference to the double).


Solution

  • The answer depends on what you want to achieve with that function. In general it is a bad idea to propagate rvalue-ness to members. However, there is already an implementation in the standard library. You can use std::get in the following way:

    template <
        std::size_t Index,
        typename Tuple,
        typename Type = decltype(std::get<Index>(std::declval<Tuple>()))>
    auto forward(Tuple&& tuple) -> Type
    {
        return std::get<Index>(std::forward<Tuple>(tuple));
    }