Is immediate temporary use of the destructor required?

GCC 7.2 and Clang 5.0 disagree in this case:

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. }; 

This behavior is part of the "C ++ 17 Guaranteed (elite copy and not associated with RVO or NRVO)."

GCC does not compile this code, but Clang does. Which one is wrong?

Perhaps this paragraph suggests that the Clang bot and GCC are standard [class.temporary]:

When an object of class X is transferred or returned from a function, if each constructor of the copy moves the constructor and destructor of X either trivial or deleted, and X has at least one non-deleted copy or move to the constructor, implementations are allowed to create a temporary object to store the function parameter or result object . The temporary object is created from the function argument or return value, respectively, and the function parameter or return object is initialized as if using an unused trivial constructor to copy the temporary one (even if this constructor is not available or will not be selected using overload permission to perform copying or moving the object). [Note. This latitude is provided to allow objects of type class transferred or returned from functions in registers. - final note]

+5
source share
2 answers

I believe this is a clang error.

From [class.temporary] :

Temporary objects are created [...] when it is necessary by the implementation to transfer or return an object of a trivially copied type (see below) and [...]

Even if the creation of a temporary object is not evaluated ([expr.prop]), all semantic restrictions must be respected as if the temporary object was created and subsequently destroyed. [Note. This includes accessibility and deletion for the selected constructor and for the destructor. However, in a special case, the operand of the decltype specifier ([expr.call]) does not introduce any time constraints; therefore, the foregoing does not apply to such a prvalue. - final note]

Copy-initialization of the return foo is the context that creates the temporary object, so semantic restrictions must still be fulfilled, which include the availability of the destructor (as the explanation explains). ~A() must be accessible in this context, but it is not, therefore, the program must be poorly formed. gcc correctly reject.

+1
source

I believe this is a gcc bug in C ++ 17. According to copy elision :

since C ++ 17

In the following cases, compilers are necessary to exclude the possibility of copying and moving class objects if the copy / move constructor and the destructor have observed side effects. They should not be present or accessible, as language rules ensure that the copy / move operation is not performed space, even conceptually:

During initialization, if the initializer expression is prvalue and the cv-unqualified version of the source type is the same class as the destination class, the initializer expression is used to initialize the target.

In a function call, if the operand of the return statement is prvalue and the return type of the function is the same as the type of this value.

Your foo function returns a prvalue object of type A and returns type foo - A, regardless of whether A has an available copy / move constructor and destructor, the copy will be omitted in C ++ 17.

0
source

Source: https://habr.com/ru/post/1272304/


All Articles