【发布时间】: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&& t) -> decltype(static_cast<void>(t.name)) {}); -
GCC 7 没有问题
-
@101010 想知道我怎么会错过这个:)
标签: c++ c++11 templates gcc c++14