1

One cannot directly use std::get with run-time arguments:

template<typename Tuple>
void get(size_t i, Tuple const& t)
{
     using std::get;
     std::cout<<get<i>(t)<<std::endl;       //error: 'i' is not a constant expression
}

int main()
{
    std::tuple<int,double> t;
    get(1,t);
}

However, one can manually map run-time to compile-time information:

template<typename Tuple>
void get_impl(size_t i, Tuple const& t, typename std::tuple_size<Tuple>::type) {}

template<size_t N, typename Tuple, typename = std::enable_if_t<std::tuple_size<Tuple>::value != N> >
void get_impl(size_t i, Tuple const& t, std::integral_constant<size_t, N>)
{
    if(i==N)
    {
        std::cout<<std::get<N>(t)<<std::endl;
    }
    else
    {
        get_impl(i, t, std::integral_constant<size_t, N+1>());
    }
}

template<typename Tuple>
void get(size_t i, Tuple const& t)
{
    get_impl(i, t, std::integral_constant<size_t, 0>());
}

which seems rather conventient to me (DEMO).

With this, one can apply arbitrary functions (which accept all tuple members) to a tuple-element chosen at run-time.

Is there a reason why this or something similar is not in the standard library? Am I missing something relevant here which hinders the proper application?

davidhigh
  • 14,652
  • 2
  • 44
  • 75
  • In the [original paper](http://open-std.org/jtc1/sc22/wg21/docs/papers/2002/n1403.pdf) `i` is an integral constant expression. As why it wasn't expanded beyond that's only guessing and thus off-topic. – edmz Jun 14 '15 at 11:24
  • 2
    I imagine that this construction isn't nearly as useful as one might think. Printing an entire tuple is useful (but doesn't require dynamic element access quite in the way you're asking for), but beyond that, I don't think I've seen the need for this outside of Stack Overflow questions. Note also that the callback would need to be a function template, and that only became feasible in a clean way with C++14. But please do try and write an example library function and see if you come up with something nice. – Kerrek SB Jun 14 '15 at 11:24
  • 1
    You would have a runtime ``get`` with linear complexity in the number of members of the tuple. To me it would look like giving ``std::list`` an ``operator[]()``. – bluescarni Jun 14 '15 at 12:49
  • @KerrekSB: I have some application in mind (I'm not a programming theorist :-)): consider a tuple of expression template classes, all having `operator[](int)`. With the above, one could access the i'th element and return the result (or, at least, the result casted to the common_type of all return types). But alternatively, type erasure would work for that as well. – davidhigh Jun 14 '15 at 13:09
  • @bluescarni: if it's about the linear effort: one can set up the same also with a logarithmic effort. – davidhigh Jun 14 '15 at 13:42
  • 1
    [`magic_switch`](http://stackoverflow.com/a/30825798/1774667) solve your problem? O(1) effort per call. – Yakk - Adam Nevraumont Jun 14 '15 at 23:57

0 Answers0