Collectives™ on Stack Overflow
Find centralized, trusted content and collaborate around the technologies you use most.
Learn more about Collectives
Teams
Q&A for work
Connect and share knowledge within a single location that is structured and easy to search.
Learn more about Teams
The following minimal example compiles with
g++ -std=c++11 -Wall tuple.cpp -o tuple
:
#include <tuple>
#include <iostream>
template<int i>
char get_elem_i(std::tuple<char, char> t)
return std::get<i>(t);
int main()
std::tuple<char, char> t('H','i');
char c = get_elem_i<0>(t);
std::cout << "The char is: " << c << std::endl;
Now, I do not want to use a template which specifies the index (the exact reason why: I have templates that are deduced automatically, and I do not want to need to specify them all). So my first try was:
char get_elem_i(int i, std::tuple<char, char> t)
return std::get<i>(t);
I understand that this can not compile. Is there any way to assure the compiler that i will be known at compile time? Maybe something like this?
char get_elem_i(compile_time_known int i, std::tuple<char, char> t)
You could use a std::array instead of a std::tuple. In the example given, the members of the tuple all have the same type.
So, we could do:
char get_elem_i(int i, std::array<char, 2> t)
return t[i];
Here's a slight variant on the example you gave to show why it's not directly possible in the general case:
???? get_elem_i(int i, std::tuple<char, struct foo, class bar> t) {
return std::get<i>(t);
What is the return type of that function? char? struct foo?
And you could always write a function like this:
char get_elem_i(int i, std::tuple<char, char> t) {
switch (i) {
case 0: return std::get<0>(t);
case 1: return std::get<1>(t);
assert(false);
–
–
–
–
–
If you can know the value of i at compile time then you can getting around specifying specifying the explicit value of i by wrapping your logic for i in aconstexpr.
For example:
#include <tuple>
#include <iostream>
constexpr int compile_time_known_i(int input) { return input / 3; }
template<int i>
char get_elem_i(std::tuple<char, char> t)
return std::get<i>(t);
int main()
std::tuple<char, char> t('H','i');
char c = get_elem_i<0>(t);
char d = get_elem_i<compile_time_known_i(3)>(t);
std::cout << "The char is: " << c << " " << d << std::endl;
Given your i's can be known at compile time, this may help clean things up (although how much sense this makes depends on your use case).
If it's the syntax of passing a parameter you are after, you could achieve this with the preprocessor - with some optional type_traits safety.
#include <tuple>
#include <iostream>
#include <type_traits>
#define get_elem_i_ct(i, t) \
std::get<i>(t); \
static_assert(std::is_integral<decltype(i)>::value, #i " must be an integral type"); \
static_assert(std::is_same<decltype(t), std::tuple<char, char>>::value, #t " must be a tuple");
int main()
std::tuple<char, char> t('H','i');
char c = get_elem_i_ct(0, t)
char d = get_elem_i_ct(1, t)
std::cout << "The char is: " << c << " " << d << std::endl;
Although this achieves the stated syntactical requirement, I wouldn't recommend using this approach in anger - there's almost certainly a better solution to your actual problem.
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.