The standard templates std::pair and std::array are special cases of std::tuple, and it stands to reason that they should have a very
Here is my implementation of tuple piecewise (it also allow to omit values with omit "keyword"). Zero overhead (no copy/move - direct construction):
http://coliru.stacked-crooked.com/a/6b3f9a5f843362e3
#include
#include
#include
struct Omit{} omit;
template
struct TupleHolder{
using fieldT = Field;
using nextT = TupleHolder;
Field field;
TupleHolder next;
TupleHolder(){}
template
TupleHolder(Omit, ValuesRef&& ... values)
: next( std::forward(values)... )
{}
template
TupleHolder(std::index_sequence, FieldValue&& field, ValuesRef&& ... values)
:
field( std::get(std::forward(field))... ),
next( std::forward(values)... )
{};
template
TupleHolder(FieldValue&& field, ValuesRef&& ... values)
: TupleHolder(
std::make_index_sequence<
std::tuple_size< std::decay_t >::value
>(),
std::forward(field),
std::forward(values)...
)
{}
};
template
struct TupleHolder{
using fieldT = Field;
Field field; // actually last
TupleHolder(){}
TupleHolder(Omit){}
template
TupleHolder(std::index_sequence, FieldValue&& field)
:
field( std::get(std::forward(field))... )
{}
template
TupleHolder(FieldValue&& field)
: TupleHolder(
std::make_index_sequence<
std::tuple_size< std::decay_t >::value
>(),
std::forward(field)
)
{}
};
template
struct GetLoop{
using type = typename T::nextT;
constexpr static decltype(auto) get(T& data) noexcept{
return GetLoop::get(
data.next
);
}
constexpr static decltype(auto) get(const T& data) noexcept{
return GetLoop::get(
data.next
);
}
constexpr static decltype(auto) get(T&& data) noexcept{
return GetLoop::get(
std::forward(data.next)
);
}
};
template
struct GetLoop{
using type = typename T::fieldT;
constexpr static type& get(T& data) noexcept{
return data.field;
}
constexpr static const type& get(const T& data) noexcept{
return data.field;
}
constexpr static type&& get(T&& data) noexcept{
return std::forward(data.field);
}
};
// ----------------------------------------------------------------------------------
// F R O N T E N D
// ----------------------------------------------------------------------------------
template
struct TuplePiecewise{
using fieldsT = TupleHolder;
TupleHolder data;
TuplePiecewise(){}
// allow copy constructor
TuplePiecewise(TuplePiecewise& other)
: TuplePiecewise(static_cast(other)) {}
template
explicit constexpr TuplePiecewise(ValuesRef&& ... values) noexcept
: data( std::forward(values)... ){}
TuplePiecewise( const TuplePiecewise& other ) = default;
TuplePiecewise( TuplePiecewise&& other ) = default;
static constexpr const std::size_t size = sizeof...(FieldTypes);
};
template
constexpr decltype(auto) get(TuplePiecewise &&list) noexcept {
return GetLoop<0, index, typename TuplePiecewise::fieldsT >::get( std::move(list.data) );
}
template
constexpr decltype(auto) get(TuplePiecewise &list) noexcept {
return GetLoop<0, index, typename TuplePiecewise::fieldsT >::get( list.data );
}
template
constexpr decltype(auto) get(const TuplePiecewise &list) noexcept {
return GetLoop<0, index, typename TuplePiecewise::fieldsT >::get( list.data );
}
Usage:
TuplePiecewise< CopyTest, int&, string, int >
list (forward_as_tuple(45,63), forward_as_tuple(i), forward_as_tuple("hghhh"), omit );
decltype(auto) o = get<2>(list);
cout << o;
Tuple inside tuple (zero overhead):
TuplePiecewise< string, TuplePiecewise > list4(forward_as_tuple("RRR"), forward_as_tuple(forward_as_tuple(10), forward_as_tuple(20)));