Vicente J. Botet Escriba wrote:
About the infamous tuple_cat challenge. tuple_cat doesn't append. tuple
cat construct a tuple with the elements of its tuple-like parameters...
That's quite true. The tuple_cat implementation in the article is a
straightforward reimplementation of Eric's tuple_cat, to illustrate the
difference in styles. It fixes one limitation of the original, but others
remain. Specifically, it doesn't work when the arguments are const
qualified, when the tuple elements are move-only (although this is a defect
in std::get), or for tuple-likes apart from std::pair.
Fixing those defects one by one:
1. tuple can be fixed by replacing
template
R tuple_cat_( mp_list, mp_list, Tp tp )
{
return R{ std::getKs::value(std::getIs::value(tp))... };
}
with
template
R tuple_cat_( mp_list, mp_list, Tp tp )
{
return R{ std::getKs::value(std::getIs::value(std::move(tp)))... };
}
This shouldn't be necessary though; it's std::get that is broken here.
2. const-qualified tuples:
template, typename
std::remove_reference<Tp>::type...>>
R tuple_cat( Tp &&... tp )
needs to be replaced with
template<class T> using remove_cv_ref =
std::remove_cv_t;
template, remove_cv_ref<Tp>...>>
R tuple_cat( Tp &&... tp )
and the same substitution needs to be done for
using list1 = mp_list...>;
3. tuple-like types:
template, remove_cv_ref<Tp>...>>
R tuple_cat( Tp &&... tp )
needs to be further massaged as follows:
template using element_ = std::tuple_element_t;
template<class T> using from_tuple_like = mp_product, mp_list<T>>;
template,
from_tuple_like...>>
R tuple_cat( Tp &&... tp )
and similarly for list1:
using list1 = mp_list...>;
With these changes, this now works:
{
std::array const t1{ 1, 2 };
std::array const t2{ 3.0f, 4.0f, 5.0f };
std::array t3{ std::unique_ptr<int>{ new
int } };
using expected = std::tuple;
auto result = ::tuple_cat( t1, std::move( t2 ), std::move( t3 ) );
static_assert( std::is_same::value, "" );
PRINT_TYPE( decltype(result) );
print_tuple( result );
}