std :: is_constructible即时上下文和朋友声明

时间:2019-03-07 22:51:56

标签: c++ language-lawyer c++17 typetraits

最近,我尝试检测特定私有构造函数的存在,并遇到一个问题,std::is_constructible仅检查即时上下文,因此无法识别任何此类构造函数。经过一番研究,我确实看到一个答案here提到正确的方法是将有问题的班级与std::is_constructible交到朋友,以使其可以访问。

要测试此方法是否有效,我尝试了以下测试代码

#include <type_traits>

class A {
private:
  template<typename, typename ...>
  friend struct std::is_constructible;

  A() = default;
};

int main() {
  static_assert(std::is_constructible<A>::value);
  static_assert(std::is_constructible_v<A>);
}

有趣的是,此方法在Visual Studio 2017中似乎可以与std::is_constructible一起使用,尽管随后我开始遇到std::is_constructible_v的问题。在其实现中,他们没有在实际的结构std::is_constructible本身上使用别名模板,而是直接调用内部使用的内在函数,而该内在函数反过来忽略了朋友声明。

考虑到这是其标准库实现的一个错误,然后我在其他编译器中进行了测试,发现clang和gcc在任何情况下都不能传递此断言,这使我想知道它是否应该像完全是这个(链接文章上的一些评论似乎暗示这是一个错误,而其他人则说它不应该考虑朋友声明)。

因此,主要问题是该代码是否应该正常工作(因为它应该能够访问私有构造函数并传递断言),并且该方法将标准定义的访问限制为立即上下文? here也提出了类似的问题,我不确定的主要事情是这种情况下“即时上下文”所意图的确切定义,因为这与链接问题中的示例稍有不同。

N4713 23.15.4.3.8 [meta.unary.prop] / 8的相关段落:

  

执行访问检查就像在与T和任何其他都不相关的上下文中一样   的Args。只有有效性的直接上下文   考虑变量初始化。

1 个答案:

答案 0 :(得分:5)

  

经过研究,我确实看到这里的一个答案提到,正确的方法是将有问题的班级与std::is_constructible进行友谊交流,以允许其访问。

不。当然不。这根本不是正确的方法。不能保证它会起作用。

此外,无法保证标准库中的friend {em>任何内容都可以做您想要的事情。标准库不是您的朋友。 P1339已在Kona中获得批准,并将更新SD-8,以赋予标准库以用户不这样做的权利……并且该库将不在乎更改是否会破坏用户友好性。< / p>

std::is_constructible_v<A>是并且应该是false

相关问题