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.