gcc и clang исключают вызов конструктора перемещения из фрагмента ниже. Это правильно?

В коде ниже объекта s класса S используется для инициализации объекта класса D с прямой инициализацией D d(s);, Функция преобразования S :: operator D () используется для преобразования объекта s во временный объект типа D, Затем gcc и clang исключают явный вызов конструктора перемещения D(&&), чтобы переместить этот временный объект в d, Увидеть живой пример.

#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);
}

Я оспариваю правильность этого решения по следующим причинам:

  1. Этот случай рассматривается в первом подпункте в п. 8.5 / 16 (N3337), в котором ничего не говорится об исключении.

    Если инициализация является прямой инициализацией, или если это
    инициализация копии, где cv-неквалифицированная версия источника
    тип — это тот же класс, или производный класс от класса
    назначения, конструкторы считаются. Применимые конструкторы
    перечисляются (13.3.1.3), а лучший выбирается через перегрузку
    разрешение (13,3). Выбранный конструктор вызывается для инициализации
    объект, с выражением инициализатора или выражением-списком в качестве его
    аргумент (ы). Если конструктор не применяется, или разрешение перегрузки
    неоднозначно, инициализация плохо сформирована.

  2. Обратите внимание, что в следующем подпункте явно упоминается возможность исключения.
  3. Вызов конструктора перемещения является явным. Как это может быть исключено?

6

Решение

Стандарт C ++ любит создавать исключения из правил, определенных в одном месте в совершенно другом месте.

Правило копирования / перемещения указано в 12.8 / 31. В вашем коде нужно исключить две операции копирования / перемещения.

Первое легко: внутри operator Dвременный объект, созданный в выражении возврата, перемещается во временный объект, представляющий возвращаемое значение функции. Пуля 3 позволяет исключить этот ход.

Вторым является перемещение возвращаемого значения временной функции в d объект. Опять же, пуля 3 разрешает исключение.

  • когда временный объект класса, который не был связан со ссылкой (12.2), будет скопирован / перемещен в объект класса с тем же типом cv-unqualified, операция копирования / перемещения может быть опущена путем создания временного объекта непосредственно в цель опущенной копии / перемещения
8

Другие решения


По вопросам рекламы ammmcru@yandex.ru
Adblock
detector