As title states, I'm wondering if it's possible to pass in a variable to std::get<>()
of a tuple?
I have a header file, which contains a struct that holds numerous params (and functions) that are used to instantiate different object types. The header file is essentially a helper to reduce redundancy in instantiation, when I am testing different classes.
I am trying to tweak the defining/initializing functions, to allow for custom parameters (non-default) to be passed into them, using a set and a variadic tuple. The set represents the indices associated with a param, and the tuple will contain the non-default values to substitute into the params. If an index (implicitly associated with a param) is present in the set, the passed in value is used in place of a default.
I have a rolling index, i
, that keeps track of the next position to retrieve an element from, in the tuple. The index is updated whenever an item is retrieved from the tuple.
Reason for using a rolling index is because some of these objects take in many params (>10) into their constructor, but I often only need to test (expected) off-nominal behaviour by passing in just 1-3 invalid parameters. As such, it would be ideal for me to not have to pass in a tuple whose size is the number of params (and filled with placeholders for the values not being substituted). While that would obviate the need to "dynamically" compute the next index i
, since it would be a 1:1 mapping, it's a bit inelegant to me.
Below is a simplified version of my code:
#include <iostream>
#include <tuple>
#include <utility>
#include <set>
struct MyStruct
{
int my_int;
char my_char;
std::string my_string;
template <typename...T>
void initParams(std::set<int> paramIndices=std::set<int>(), std::tuple<T...> customParams=std::tuple<T...>())
{
auto i=0;
// size of set and tuple must match
if(paramIndices.size()==std::tuple_size<std::tuple<T...>>{})
{
// if values are present, substitute them
// these throw an error, which is understandable; i is not const, const template argument is required for std::get<>
my_int = paramIndices.contains(0) ? std::get<i++>(customParams) : 0;
my_char = paramIndices.contains(1) ? std::get<i++>(customParams) : 'a';
my_string = paramIndices.contains(2) ? std::get<i++>(customParams) : "hello";
// attempt to use as_const() to introduce const-ness
// why do these throw an error as well?
my_int = paramIndices.contains(0) ? std::get<std::as_const(i++)>(customParams) : 0;
my_char = paramIndices.contains(1) ? std::get<std::as_const(i++)>(customParams) : 'a';
my_string = paramIndices.contains(2) ? std::get<std::as_const(i++)>(customParams) : "hello";
}
}
/* do stuff with params
...
*/
};
int main()
{
std::set<int> s{0, 2};
std::tuple t{500, "world"};
MyStruct().initParams(s, t);
}
I am using CMake for the larger project, but for this simplified version, I am compiling as:
g++ -std=c++20 test.cpp
as_const
was introduced in c++17, and the set method contains()
was introduced in c++20.