Question

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?

Was it helpful?

Solution

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 ) );
}

http://ideone.com/ZdoWI7

All the decay is necessary because the metafunctions discriminate between tuple and tuple &.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top