mardi 24 janvier 2017

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?

Aucun commentaire:

Enregistrer un commentaire