2013-07-09 1 views
3

Мне нужна вспомогательная функция кортежа, которая, если запрошенный тип не существует в кортеже, возвращает построенный по умолчанию тип null.tuple - get_or вспомогательная функция

например.

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

Наверное, мне нужна магия слияния, но я не совсем понял это. Какие-либо предложения?

+0

Вы не должны компилировать первую строку. Вам нужно передать второй аргумент конструктора. – juanchopanza

+0

@juanchopanza - думаю, что первая строка на самом деле вопрос. Он хочет иметь возможность инициализировать кортеж таким образом и установить 2-й аргумент по умолчанию – asafrob

+0

@asafrob Ah OK. То, как проблема представляется, бросает меня. Никакая вспомогательная функция не устранит эту ошибку компилятора. – juanchopanza

ответ

2

Вот помощник tuple_index Я лежал вокруг, который возвращает индекс данного типа в std::tuple. (Это легко может быть настроен на работу с предикатом, такого как 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 > {}; 

Вы могли бы построить на нем так:

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

Все decay необходимо, поскольку метафайлы различаются между tuple и tuple &.

+0

Отлично! Хотя я надеялся на более простую вспомогательную функцию, используя boost mpl или fusion? – ronag

+0

Это довольно просто, просто подробный из-за 'decay', который я скопировал. Вы можете определить это путем отправки через посредника. Также я вроде сомневаюсь, что 'forward' что-то делает; Я просто добавил его защитно. – Potatoswatter

 Смежные вопросы

  • Нет связанных вопросов^_^