Gcc and clang both return a call to the move constructor in the snippet below. It's right?

In the code below, an object s class s used to initialize an object of class D using direct initialization D d(s); . The conversion function S :: operator D () is used to convert the object s to a temporary object of type D Then gcc and clang both return an explicit call to the D(&&) move constructor to move this temporary object to D See a live example .

 #include <iostream> struct D; struct S{ operator D(); }; struct D{ D(){} D(D&&) { std::cout << "move constructor" << '\n'; } }; S::operator D() { std::cout << "conversion function" << '\n'; return D(); } int main() { S s; D d(s); } 

I dispute the correctness of this decision for the following reasons:

  • This case is dealt with at the first point of subparagraph in ยง 8.5 / 16 (N3337), which refers to an exception.

    If initialization is direct initialization or if it is copy-initialization, where the cv-unqualified version of the type source is the same class as the derived class of the destination class, the constructors. The corresponding constructors are listed (13.3.1.3), and the best one is selected by overloading the resolution (13.3). The constructor selected in this way is called to initialize an object with an initializer expression or a list of expressions as its argument (s). If the constructor is not used or the overload resolution is ambiguous, initialization is poorly formed.

  • Please note that the next point of the subclause clearly indicates the possibility of elite.
  • The call to the move constructor is explicit. How can it be eliminated?
+6
source share
1 answer

The C ++ standard likes to throw exceptions in rules defined in one place in a completely different place.

Elimination rules for copying / moving are specified in 12.8 / 31. There are two copy / move operations in your code.

The first is easy: inside operator D temporary constructed in the return expression is moved to the temporary, representing the return value of the function. Bullet 3 allows you to exclude this move.

The second is moving the return value of the temporary function to object d . Again, bullet 3 allows elite.

  • when a temporary class object that was not attached to the link (12.2) is copied / transferred to the class object with the same cv-unqualified type, the copy / move operation can be omitted by directly constructing the temporary object in the target of the missed copy / move
+8
source

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


All Articles