【问题标题】:Why std::is_constructible stops at immediate context?为什么 std::is_constructible 在直接上下文中停止?
【发布时间】:2016-05-02 13:32:31
【问题描述】:

源自this话题。也和这个topic有关。

我的问题是为什么std::is_constructible 会在当前上下文中停止?我认为std::is_constructible 的用户会期望它能够充分发挥作用并给出准确的答案。有了这个直接的上下文,你可能会让std::is_constructible 给你开绿灯,但在你实际这样做时却得到一个硬编译器错误。这不会违背std::is_constructible 的最初目标和目的吗?现在,它对我来说基本上看起来毫无用处。我猜std::looks_constructible_at_first_sight 将是当前语义的更好名称:(

【问题讨论】:

  • 它简化为Reachability problem,这是NP-hard。
  • @erip Wow~ 所以,基本上不是我们不想做,而是我们这里有技术问题?但我认为简单的 SFINAE 就可以完成这项工作。没有?
  • SFINAE 也停在当前上下文。
  • @T.C.但最终,编译器将深入工作并得出一个准确的答案。我们可以利用这个事实吗?
  • 首先,您可能希望重载解决方案“深入工作”。编译时间会飙升。其次,现有实现可能无法从实例化堆栈深处的错误中优雅地恢复。看看 MSVC 与表达 SFINAE 的斗争。

标签: c++ language-lawyer c++14 template-meta-programming typetraits


【解决方案1】:

如果你的构造函数的签名比它应该的要宽松得多,就是问题 - 不是is_constructible的实现。在你原来的例子中,

template <typename... Ts, typename=decltype(base{std::declval<Ts>()...})>
aggregate_wrapper(Ts&&... xs)
    : base{std::forward<Ts>(xs)...} {/*…*/}

完成这项工作。如果is_constructible "spuriously" 亮了绿灯,那么您的构造函数模板可能会被虚假选择而不是其他构造函数,因为重载解析发现它是最佳匹配。

但是,重载解决方案并非旨在仅给出真正的否定/肯定:它旨在在给定适当参数的情况下找到最佳匹配,或者如果参数足够不合适,则不产生任何结果。 is_constructible 在某种意义上可能是肤浅的,但这就是特征的用途 - 检查签名,这是一个实体在重载解析和 SFINAE 领域的表示 - 不会阻止您的函数模板接受所有内容,而只是实际实例化一小部分论据的余量。
那是你的责任,如果你遇到了,你会从is_constructible和高效的编译中得到正确的结果。这绝对比is_constructible 的不间断操作和函数模板调用中大量隐藏规则的高编译时间要好。

【讨论】:

  • base{std::declval&lt;Ts&gt;()...} 是否等同于 base{std::forward&lt;Ts&gt;(std::declval&lt;Ts&gt;())...}
  • @Lingxi 是的。 declval 返回 add_rvalue_reference,它产生与 forward 完全相同的类型(检查它的返回类型!)。
  • 我不知道你的代码 sn-p 来自哪里,但这解决了我的问题!谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多