非物质化的临时性是否需要可以访问析构函数?

Oli*_*liv 5 c++ temporary c++17

GCC 7.2和Clang 5.0在这种情况下不一致:

struct A;

A foo();

struct A
  {
  static void bar()
     {
     foo();
     }
  private:
  ~A()=default;
  };

A foo()
  {
  return {};
  //GCC error: A::~A() is private in this context.
  };
Run Code Online (Sandbox Code Playgroud)

此行为是"c ++ 17保证(复制省略并且与RVO或NRVO无关)"的一部分.

GCC不会编译此代码,但Clang会这样做.哪一个错了?

也许这段话说机器人Clang和GCC符合标准[class.temporary]:

当类类型X的对象传递给函数或从函数返回时,如果X的每个复制构造函数,移动构造函数和析构函数都是微不足道的或删除的,并且X至少有一个未删除的复制或移动构造函数,则实现是允许创建一个临时对象来保存函数参数或结果对象.临时对象分别由函数参数或返回值构造,并且函数的参数或返回对象被初始化,就好像通过使用未删除的普通构造函数来复制临时对象(即使该构造函数不可访问或不会被选中)通过重载决策来执行对象的复制或移动).[注意:允许此纬度允许类类型的对象传递给寄存器中的函数或从寄存器中的函数返回. - 结束说明]

Bar*_*rry 1

我相信这是一个 clang bug。

\n

来自[class.temporary]

\n
\n

当实现需要传递或返回普通可复制类型的对象时,会创建临时对象(见下文),并且 [...]

\n

即使临时对象的创建未被评估([expr.prop]),也应遵守所有语义限制,就好像临时对象已被创建并随后被销毁一样。[\xe2\x80\x89注意:这包括所选构造函数和析构函数的可访问性以及是否被删除。然而,在decltype-specifier ([expr.call])操作数的特殊情况下,没有引入临时变量,因此前述内容不适用于此类纯右值。\xe2\x80\x94\xe2\x80\x89尾注\xe2\x80\x89]

\n
\n

返回的复制初始化foo是创建临时对象的上下文,因此仍然必须遵循语义限制 - 其中包括析构函数的可访问性(正如注释有助于阐明的那样)。~A()在此上下文中必须可访问,但事实并非如此,因此该程序应该是格式错误的。gcc 拒绝是正确的。

\n