2015-11-25 3 views
3
template<class... Ts, class T> 
constexpr auto contains(T&&){ 
    auto types = hana::to<hana::tuple_tag>(hana::tuple_t<Ts...>); 
    return hana::bool_c<hana::find(types, hana::type_c<T>) != hana::nothing>; 
} 

auto ht = hana::make_tuple(1,2,3,'c'); 

auto ht1 = hana::filter(ht, [](auto t){ 
    return contains<int,float,double>(t); 
}); 
//prints 0 
std::cout << hana::size(ht1) << std::endl; 

Я не уверен, правильно ли использую boost hana, но contains, похоже, работает.Фильтрация кортежа в boost hana

std::cout << contains<int,float,double>(5) << std::endl; // 1 
std::cout << contains<int,float,double>('c') << std::endl; // 0 
std::cout << contains<int,float,double>(5.0f) << std::endl; // 1 

Почему размер ht1 0?

ответ

4

Проблема здесь на самом деле не имеет ничего общего с Hana, он должен делать с тем, как выводятся универсальные ссылки. Просто, чтобы прояснить ситуацию, hana::type_c<T> == hana::type_c<U> точно эквивалентен std::is_same<T, U>{}. При сравнении hana::type s отсутствует ссылочный или cv-квалификатор. Вы можете посмотреть различные статьи (например, this или this) для этих правил.

Теперь позвольте мне просмотреть ваш код и изменить некоторые вещи с комментариями. Во-первых,

auto types = hana::to<hana::tuple_tag>(hana::tuple_t<Ts...>); 

является излишним, потому что вы уже создает hana::tuple с hana::tuple_t. Следовательно, достаточно hana::tuple_t<T...>. Во-вторых, есть такая строка:

return hana::bool_c<hana::find(types, hana::type_c<T>) != hana::nothing>; 

Вместо проверки hana::find(...) != hana::nothing, я бы вместо этого использовать hana::contains, выражающий ваши намерения лучше и может быть более оптимизирован тоже. В общем, и особенно с библиотекой метапрограммирования с Ханой, не пытайтесь рассуждать о том, что будет быстрее. Просто сформулируйте свои намерения как можно яснее и надейтесь, что я правильно выполнит свою работу на стороне реализации :-). Таким образом, вы будете в конечном итоге с

return hana::bool_c<hana::contains(types, hana::type_c<T>)>; 

Теперь, что hana::bool_c<...> действительно является излишним, поскольку hana::contains уже возвращает булево integral_constant. Таким образом, выше эквивалентно более простой

return hana::contains(types, hana::type_c<T>); 

Наконец, положив все биты вместе и упрощения, вы получите

template<class... Ts, class T> 
constexpr auto contains(T&&){ 
    return hana::contains(hana::tuple_t<Ts...>, hana::type_c<T>); 
} 

Я лично не любитель принимать T&& в качестве аргумента, когда все, что вы хотите, на самом деле является типом этого объекта. Действительно, это заставляет вас фактически предоставить объект функции contains, который может быть громоздким при некоторых обстоятельствах (что, если у вас нет объекта вокруг?).Кроме того, это может привести к путанице, чтобы быть сравнение значений с типами:

contains<int, char, double>(3.5) // wtf, 3.5 is not in [int, char, double]! 

Вместо этого я хотел бы написать следующее, если это был мой собственный код:

template<class... Ts, class T> 
constexpr auto contains(T type){ 
    return hana::contains(hana::tuple_t<Ts...>, type); 
} 

// and then use it like 
contains<int, char, double>(hana::type_c<double>) 

Но это часть интерфейса вашего функции, и я думаю, вы лучший судья, чем я, чтобы знать, что ваши потребности в плане интерфейса.

3

Проблема заключается в T&&, я думаю, что он выводит тип, чтобы быть типа T&, что означает, что hana::type_c<T> != hana::type_c<T&> Исправление покинуть &&, потому что они не нужны.

template<class... Ts, class T> 
constexpr auto contains(T){ 
    auto types = hana::tuple_t<Ts...>; 
    return hana::find(types, hana::type_c<T>) != hana::nothing; 
} 
2

Просто чтобы добавить в свой ответ, ваш ht1 звал contains с t именующим. Ниже показано T&& в случае прохождения RValue и именующее выражение:

#include<boost/hana.hpp> 

namespace hana = boost::hana; 

template<class T> 
void test1(T&&) { 
    static_assert(hana::type_c<T> == hana::type_c<int>, ""); 
} 

int main() { 
    static_assert(hana::type_c<int> != hana::type_c<int&&>, ""); 
    test1(5); 
    int x = 5; 
    test1(x); //fails 
} 

выход лязг:

main.cpp:7:3: error: static_assert failed "" 
    static_assert(hana::type_c<T> == hana::type_c<int>, ""); 
^   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
main.cpp:14:3: note: in instantiation of function template specialization 'test1<int &>' requested here 
    test1(x); //fails 
^
1 error generated.