Zizheng Tai
Zizheng Tai

Reputation: 6626

Casting in trailing return type causes SFINAE to fail

I have re-implemented boost::hana::is_valid for study purpose. The use case is:

struct Person {
    std::string name;
};

int main()
{
    auto has_name = is_valid([](auto&& t) -> decltype((void) t.name) {});

    Person jon{"snow"};
    static_assert(has_name(jon), "");
    static_assert(!has_name(1), "");
}

Implementation:

namespace detail {

template<typename F>
struct is_valid_impl {
    template<typename T, typename = std::result_of_t<F&&(T&&)>>
    constexpr bool operator()(T&&) const noexcept { return true; }

    constexpr bool operator()(...) const noexcept { return false; }
};

}  // namespace detail

template<typename F>
constexpr auto is_valid(F&&)
{
    return detail::is_valid_impl<F>{};
}

However, I don't know why Hana's user guide recommends casting the type of the wanted member to void (see here); can't we just use decltype(t.name) instead of decltype((void) t.name)?

Moreover, the cast to void causes the tests to fail in GCC < 5.3, while without the cast the code works for GCC 5.1+. What could be the reason?

Upvotes: 4

Views: 172

Answers (1)

Marco A.
Marco A.

Reputation: 43662

Can't be more explicit than the documentation:

@snippet example/tutorial/introspection.cpp non_static_member_from_object

Notice how we cast the result of x.member to void? This is to make sure that our detection also works for types that can't be returned from functions, like array types.

Link to the docs line

Upvotes: 2

Related Questions