I need a tuple helper function that if a requested type does not exist in the tuple it returns a default constructed null type.
e.g.
std::tuple<bool, int> tuple(true, 0);
static_assert(std::is_same<decltype(get_or<double, std::nullptr_t>(tuple)),
std::nullptr_t>::value, "");
assert(get_or<double, std::nullptr_t>(tuple) == nullptr);
I guess I need some boost fusion magic but I haven't quite figured it out. Any suggestions?
Here is a tuple_index
helper I have lying around, which returns the index of a given type in a std::tuple
. (It can easily be adjusted to work with a predicate such as is_convertible
.)
template< typename elem, typename tup, std::size_t offset = 0 >
struct tuple_index
: std::integral_constant< std::size_t, offset > {};
template< typename elem, typename head, typename ... tail, std::size_t offset >
struct tuple_index< elem, std::tuple< head, tail ... >, offset >
: std::integral_constant< std::size_t, tuple_index< elem, std::tuple< tail ... >, offset + 1 >::value > {};
template< typename elem, typename ... tail, std::size_t offset >
struct tuple_index< elem, std::tuple< elem, tail ... >, offset >
: std::integral_constant< std::size_t, offset > {};
You could build on it like this:
template< typename result, typename fallback, typename tuple >
typename std::enable_if< tuple_index< result, typename std::decay< tuple >::type >::value
== std::tuple_size< typename std::decay< tuple >::type >::value,
fallback >::type
get_or( tuple && t ) { return {}; }
template< typename result, typename fallback, typename tuple >
typename std::enable_if< tuple_index< result, typename std::decay< tuple >::type >::value
!= std::tuple_size< typename std::decay< tuple >::type >::value,
result >::type
get_or( tuple && t ) {
return std::get< tuple_index< result, typename std::decay< tuple >::type >::value >
( std::forward< tuple >( t ) );
}
All the decay
is necessary because the metafunctions discriminate between tuple
and tuple &
.