【问题标题】:std::is_constructible immediate context and friend declarationsstd::is_constructible 直接上下文和友元声明
【发布时间】:2019-03-07 22:51:56
【问题描述】:

最近我试图检测特定私有构造函数的存在并遇到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 在任何情况下都无法通过此断言,这让我怀疑它是否应该像这样工作这一点都没有(链接帖子上的一些 cmets 似乎暗示这是一个错误,而其他人则说它不应该考虑朋友声明)。

因此,主要问题是该代码是否可以正常工作(如它是否应该能够访问私有构造函数并传递断言),而标准定义的访问仅限于即时上下文? here 也提出了类似的问题,我不确定的主要是在这种情况下“直接上下文”的确切定义,因为这与链接问题中的示例略有不同。

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

访问检查是在与 T 和任何无关的上下文中执行的 的Args。只有直接上下文的有效性 考虑变量初始化。

【问题讨论】:

  • 大部分情况下,friend struct std::is_constructible; 不能保证通过您的任何断言。

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


【解决方案1】:

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

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

此外,无法保证标准库中的friending anything 会按照您的意愿行事。标准库不是你的朋友P1339 已在 Kona 中获得批准,并将更新 SD-8 以赋予标准库假定用户不这样做的权利......并且库不会关心更改是否会破坏用户友谊。

std::is_constructible_v&lt;A&gt; 是并且应该是false

【讨论】:

  • C++ 概念是否旨在消除友谊带来的可访问性限制?毕竟,根据 cppreference.com,你不能和一个概念交朋友?
【解决方案2】:

“变量初始化的即时上下文”是特指is_constructible_v,它是一个变量模板,用相同的参数初始化为is_constructible的值。也就是说,初始化发生在代码之外,因此代码中获取所述变量值的上下文与构造函数的可访问性无关。无论从哪里访问,获取的值都是相同的。

加上第一句话,该标准有效地表明“这只寻找可公开访问的东西”。

【讨论】:

    猜你喜欢
    • 2017-01-19
    • 2016-05-02
    • 1970-01-01
    • 1970-01-01
    • 2013-03-31
    • 2012-09-19
    • 1970-01-01
    • 2014-07-03
    • 2014-08-07
    相关资源
    最近更新 更多