Boost.Hana offers boost::hana::is_valid to check whether a SFINAE-friendly expression is valid.
You can use it like this
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), "");
However, there's a note about the argument to is_valid being a nullary function:
To check whether calling a nullary function
fis valid, one should use theis_valid(f)()syntax. […]
How can I even use it by passing to it a nullary function? I mean, if a function is nullary, then how is its body gonna have any dependent context to which SFINAE can apply?
I think that maybe "lambda captures" might have something to do with the answer, but I can't really figure it out how.
Use case is that of checking that
fis actually nullary, e.gwhat the documentation says is that unlike functions of non zero arity, the
is_validpredicate can only be invoked in the form:reminder: to check whether e.g. a 2 arguments function call is valid you can say:
Take for example the following Demo
It may be obvious, but you have to keep in mind that SFINAE does not happen ON
f0orf1. SFINAE happens in the guts ofis_validbetween the different flavors ofis_valid_impl(comments mine):So your question
has little meaning since SFINAE does not happen on the user provided function. After all, we are setting up nothing to enable SFINAE on our functions. Implementing SFINAE requires to provide more than 1 candidates that "guide" the instantiation process (check SFINAE sono buoni).
The term "SFINAE friendly" here, has to do with
f(our function) being usable as type parameter for the SFINAE implementation inis_valid. For example, if in our Demofwas overloaded (replacef1(int)withf0(int)) you would get a substitution error:because when the compiler reaches the deepest point of
is_valid_implit tries to instantiate the favorable version (version 1, that doesn't have...parameter) but it cannot tell what the type ofFis and produces a hard error.For reference, the way SFINAE works is that if it could use type
F, the compiler would:1true(so IT IS valid)2(substitution error is not a failure) which does not use typeFasF(Args...)and hence produce afalse.