The problem here actually has nothing to do with Hana, it has to do with the way universal references are deduced. Just to clear up things, hana::type_c<T> == hana::type_c<U>
is precisely equivalent to std::is_same<T, U>{}
. There is no reference or cv-qualifier removing when comparing hana::type
s. You can look at various articles (like this or this) for these rules.
Now, let me go through your code and modify some things, with comments. First,
auto types = hana::to<hana::tuple_tag>(hana::tuple_t<Ts...>);
is redundant, because you're already creating a hana::tuple
with hana::tuple_t
. Hence, hana::tuple_t<T...>
only is sufficient. Secondly, there's this line:
return hana::bool_c<hana::find(types, hana::type_c<T>) != hana::nothing>;
Instead of checking hana::find(...) != hana::nothing
, I would instead use hana::contains
, which expresses your intent better and might be more optimized too. In general, and especially with a metaprogramming library with Hana, don't try to reason as to what will be faster. Just state your intent as clearly as possible and hope for me to do my job properly on the implementation side :-). Hence, you'll end up with
return hana::bool_c<hana::contains(types, hana::type_c<T>)>;
Now, that hana::bool_c<...>
really is redundant, because hana::contains
already returns a boolean integral_constant
. Hence, the above is equivalent to the simpler
return hana::contains(types, hana::type_c<T>);
Finally, putting all the bits together and simplifying, you get
template<class... Ts, class T>
constexpr auto contains(T&&){
return hana::contains(hana::tuple_t<Ts...>, hana::type_c<T>);
}
I'm personally not a fan of taking the T&&
as an argument, when all you want is actually the type of that object. Indeed, that forces you to actually provide an object to contains
function, which might be unwieldy in some circumstances (what if you don't have an object around?). Furthermore, it can be confusing to be comparing values with types:
contains<int, char, double>(3.5) // wtf, 3.5 is not in [int, char, double]!
Instead, I would write the following if it was my own code:
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>)
But that is part of the interface of your function, and I guess you are a better judge than I to know what your needs are in terms of interface.