【问题标题】:Casting in trailing return type causes SFINAE to fail转换尾随返回类型会导致 SFINAE 失败
【发布时间】:2017-06-09 07:21:04
【问题描述】:

出于学习目的,我重新实现了boost::hana::is_valid。用例是:

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), "");
}

实施:

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>{};
}

但是,我不知道为什么 Hana 的用户指南建议将所需成员的类型转换为 void(参见 here);我们不能只使用decltype(t.name) 而不是decltype((void) t.name) 吗?

此外,转换为 void 会导致测试在 GCC fail,而如果没有转换代码 works 则用于 GCC 5.1+。可能是什么原因?

【问题讨论】:

  • 使用 static_cast 代替 C-cast 似乎可以解决问题:Demo
  • 如果您阅读手册中说:注意我们如何将x.member 的结果转换为void这是为了确保我们的检测也适用于无法从函数返回的类型,例如数组类型
  • 我倾向于说编译器错误,因为如果我使用 static_cast 而不是 C 风格的转换,一切都很好:auto has_name = is_valid([](auto&amp;&amp; t) -&gt; decltype(static_cast&lt;void&gt;(t.name)) {});
  • GCC 7 没有问题
  • @101010 想知道我怎么会错过这个:)

标签: c++ c++11 templates gcc c++14


【解决方案1】:

不能比文档更明确:

@sn-p example/tutorial/introspection.cpp non_static_member_from_object

注意我们如何将x.member 的结果转换为void这是为了确保 我们的检测也适用于无法从函数返回的类型, 像数组类型。

Link to the docs line

【讨论】:

    猜你喜欢
    • 2019-10-22
    • 2017-03-16
    • 2013-05-11
    • 2015-09-10
    • 1970-01-01
    • 1970-01-01
    • 2017-12-17
    • 2018-05-12
    • 1970-01-01
    相关资源
    最近更新 更多