Assuming I have struct
and std::tuple
with same type layout:
struct MyStruct { int i; bool b; double d; }
using MyTuple = std::tuple<
We can use structured bindings to convert a struct into a tuple with a bit of work.
Struct-to-tuple is very awkward.
template
struct to_tuple_t;
template<>
struct to_tuple_t<3> {
template
auto operator()(S&& s)const {
auto[e0,e1,e2]=std::forward(s);
return std::make_tuple(e0, e1, e2);
}
};
Now, write a to_tuple_t
for each size you want to support. This gets tedious. Sadly I know of no way to introduce a parameter pack there.
template
auto to_tuple(S&& s) {
return to_tuple_t{}(std::forward(s));
}
I know of no way to calculate the value of N
required either. So you'd have to type the 3
in auto t = to_tuple<3>(my_struct);
when you call it.
I am not a master of structured bindings. There is probably a &&
or &
or a decltype that would permit perfect forwarding on these lines:
auto[e0,e1,e2]=std::forward(s);
return std::make_tuple(e0, e1, e2);
but without a compiler to play with, I'll be conservative and make redundant copies.
Converting a tuple into a struct is easy:
template
S to_struct( std::index_sequence, Tup&& tup ) {
using std::get;
return {get(std::forward(tup))...};
}
template
S to_struct( Tup&&tup ) {
using T=std::remove_reference_t;
return to_struct(
std::make_index_sequence{}>{},
std::forward(tup)
);
}
SFINAE support based off tuple_size
might be good for to_struct
.
The above code works with all tuple-likes, like std::pair
, std::array
, and anything you custom-code to support structured bindings (tuple_size
and get
).
Amusingly,
std::array arr{1,2,3};
auto t = to_tuple<3>(arr);
works and returns a tuple with 3 elements, as to_tuple
is based on structured bindings, which work with tuple-likes as input.
to_array
is another possibility in this family.