I am storing the variadic arguments to an object constructor inside a std::tuple
and so far so good. But when calling an object function using the stored arguments and std::get<>()
, I will be thrown a compile-time assertion failure that I simply don't understand. This will happen only when all arguments are not each of a different type.
The compiler error message is:
msvc\14.16.27023\include\tuple(934): error C2338: duplicate type T in get(tuple)
mcve below:
#include <tuple>
#include <iostream>
using namespace std;
template<class... Args>
struct store_in_tuple {
tuple<Args...> m_tuple_args;
store_in_tuple(Args... args) : m_tuple_args{ args... } {}
void func() {
func_tuple(std::get<Args>(m_tuple_args)...);
}
void func_tuple(Args... args) {}
};
int main(int argc, char** argv) {
store_in_tuple<int, float, double, int> sit1(1, 2.0f, 3.0, 4);
sit1.func(); // <- not ok
store_in_tuple<int, float, double, size_t> sit2(1, 2.0f, 3.0, 4);
sit2.func(); // <- ok
return 0;
}
Why does this happen and is there a workaround ?
Use C++17 std::apply()
to pass all the elements of a tuple to a function.
std::apply([&](auto... x){ func_tuple(x...); }, m_tuple_args);
You insist on staying with C++14?
No problem, cppreference.com shows a short and simple production-quality example-implementation.
Alternatively, you can work directly with std::make_index_sequence
to get unique indices instead of duplicated types.