简体   繁体   中英

What is the advantage of Hana's type_c-and-declval dance when querying whether a SFINAE-friendly expression is valid?

On the one hand, the function boost::hana::is_valid is presented as follows

Checks whether a SFINAE-friendly expression is valid.

Given a SFINAE-friendly function, is_valid returns whether the function call is valid with the given arguments. Specifically, given a function f and arguments args... ,

 is_valid(f, args...) == whether f(args...) is valid

The result is returned as a compile-time Logical .

and an example of the usage accompanies it (from the same linked page):

    struct Person { std::string name; };
    auto has_name = hana::is_valid([](auto&& p) -> decltype((void)p.name) { });
 
    Person joe{"Joe"};
    static_assert(has_name(joe), "");
    static_assert(!has_name(1), "");

where we see that the lambda fed to is_valid is in turn fed with the actual object that we feed to has_name .

On the other hand, the book C++ Templates - The Complete Guide presents a very similar solution (and indeed the authors cite Boost.Hana and Loius Dionne ), which I omit for now the details of. This solution, however, is used in a slightly different way:

constexpr auto hasFirst = isValid([](auto x) -> decltype((void)valueT(x).first) {});
static_assert(!hasFirst(type<int>));
struct S { int first; };
static_assert(hasFirst(type<S>));

The above assumes the existence of valueT and type defined/declared below

template<typename T>
struct TypeT {
  using Type = T;
};

template<typename T>
constexpr auto type = TypeT<T>{};

template<typename T>
T valueT(TypeT<T>);

Now, if I understand correctly, valueT and type correspond roughly to boost::hana::traits::declval and boost::hana::type_c , so the example from the book should map to the following

constexpr auto hasFirstH = is_valid([](auto x) -> decltype((void)traits::declval(x).first) {});
static_assert(!hasFirst(hana::type_c<int>));
struct S { int first; };
static_assert(hasFirst(hana::type_c<S>));

But what is the advantage of this?

In this answer from Louis Dionne I initially understood that it's a matter of taste, but then I thought that might be the case for that specific scenario and not in general.

While writing the question, I've searched more an more (to put relevant links in it, mainly), and I eventually did find the answer in the documentation of Boost.Hana at Boost.Hana > User Manual > Introspection > Checking expression validity > Non-static members : the use of hana::type_c to wrap a type T in an object (not of type T , but of type hana::type<T> !) and hana::declval to unwrap it is useful to write those type traits when there's no object around.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM