I have a variable i
of type std::size_t
and a tuple of type std::tuple
. I want to get the i
-th element of the tuple. I tried this:
// bindings... is of type const T&...
auto bindings_tuple = std::make_tuple(bindings...);
auto binding = std::tuple_element<i, const T&...>(bindings_tuple);
But I get this compile error saying that the first template argument must be an integral constant expression:
error: non-type template argument of type '
std::size_t
' (aka 'unsigned long
') is not an integral constant expression
Is it possible to get the i
-th element of a tuple, and how to do that?
I would like to do this without using boost, if possible.
This is probably not what OP wants, but anyway, it is possible to return the i-th element using a run-time i provided you return a variant type such as
boost::variant
orboost::any
,For example:
will print:
(The
boost::variant<T...>
requires g++ 4.7)The question here, what would be the type return type if that would be possible? It has to be known at compile time, but tuple may contain elements of different types.
Let's assume we have a tuple of three elements:
Apparently, getting N-th element doesn't make much sense. What type would it be? It's not known until runtime. However, rather than getting N-th element you can apply a function to it, given that all elements support some common protocol:
This code "dynamically" processes element, given the index
n
. The common protocol in this example is functionfunc
which can do something meaningful with all possible types used in the tuple.However, writing such code by hand is tedious, we want to make it more generic. Let's start with extracting the application function, so we can reuse same
process
function for different functors:In this case
F
could be implemented as something like:Let's make compiler to generate all of that code, let's make it generic:
Usage:
Making it completely generic is another story, though. At least it needs to be independent of the tuple type. Then, you probably want to generify return type of the functor, so you can return meaningful result. Third, making functor to accept extra parameters.
P.S. I am not real C++ developer, so the approach above could be total nonsence. However, I found it useful for my microcontroller project where I want as much as possible to be resolved at compile time and yet be generic enough, so I can shuffle things around easily. For example, a "menu" in my project is basically a tuple of "actions", there each action is a separate class which supports simple protocol like "print your label at current position on LCD" and "activate and run your UI loop".
You cannot. That's not what a tuple is for. If you need dynamic access to an element, use
std::array<T,N>
, which is almost identical tostd::tuple<T,...,T>
but gives you the dynamic[i]
-operator; or even a fully dynamic container likestd::vector<T>
.This is possible:
This code will print:
Working sample on ideone: sample