c++ - std::is_constructible 直接上下文和友元声明

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

最近我试图检测特定私有(private)构造函数的存在,但遇到了 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 在任何情况下都无法通过这个断言,这让我想知道它是否应该像这一点(链接帖子上的一些评论似乎暗示这是一个错误,而其他人则说它不应该考虑 friend 声明)。

因此,主要问题是这段代码是否应该按照标准定义的访问被限制在直接上下文中的方式正确工作(比如它是否应该能够访问私有(private)构造函数并传递断言)?也有人提出了类似的问题here ,我不确定的主要事情是在这种情况下“直接上下文”的确切定义,因为这与链接问题中的示例略有不同。

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

Access checking is performed as if in a context unrelated to T and any of the Args. Only the validity of the immediate context of the variable initialization is considered.

最佳答案

After some research I did see that one answer here mentioned that the proper way is to friend the class in question with std::is_constructible to allow it to have access.

没有。当然不。这根本不是正确的方法。无法保证这会奏效。

此外,我们无法保证 friend调用标准库中的任何 将执行您想要的操作。标准库不是你的 friend P1339在科纳获得批准,将更新SD-8赋予标准库假设用户不会这样做的权利......并且库不会关心更改是否会像这样破坏用户友元。

std::is_constructible_v<A>是,应该是,false .

关于c++ - std::is_constructible 直接上下文和友元声明,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55054080/

相关文章:

C++ - 使用 const 引用来延长临时成员,好的还是 UB?

c++ - 什么时候私有(private)构造函数不是私有(private)构造函数?

c++ - 直接初始化与直接列表初始化 (C++)

c++ - 使用模板模板参数的模板参数

c++ - Qt 嵌套模型 View

c++ - C++ 中的动态链接不起作用

c++ - 以下代码会在 C++ 中引起问题吗?

c++ - 我们可以在 noexcept 规范中引用成员变量吗?

c++ - 类(模板)成员函数体内的 ADL 查找

c++ - 无效打印功能出错