Проблема здесь на самом деле не имеет ничего общего с 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>)
Но это часть интерфейса вашего функции, и я думаю, вы лучший судья, чем я, чтобы знать, что ваши потребности в плане интерфейса.