Почему эта прямая инициализация действительна?(C ++ 17) - PullRequest
0 голосов
/ 26 октября 2018

Рассмотрим следующие два класса:

class B
{
public:
   B() { }
   B(const B& b) = delete; //Move ctor not implicitly declared
};


class A
{
public:
   A() { }

   operator B()
   {
       return B();
   }
};

Я могу понять, почему этот код прекрасно компилируется:

A a;
B b = a;

Следуя правилам copy-initialization ,объект "a" преобразуется в значение типа B, и поскольку в C ++ 17 конструктор копирования больше не нужен, ошибки нет:

Если T является типом класса, а cv- Неограниченная версия другого типа не является T или не получена из T, или если T не является типом класса, но тип другого является типом класса, определяемые пользователем последовательности преобразования могут преобразовываться из другого типа в T(или для типа, полученного из T, если T является типом класса и доступна функция преобразования), и выбирается лучший из них с помощью разрешения перегрузки.Результат преобразования, который является prvalue временным (до C ++ 17) prvalue выражением (начиная с C ++ 17), если использовался конвертирующий конструктор, затем используется для прямой инициализации объекта.Последний шаг обычно оптимизируется, и результат преобразования создается непосредственно в памяти, выделенной для целевого объекта, но соответствующий конструктор (перемещение или копирование) должен быть доступен, даже если он не используется.(до C ++ 17)

Однако почему эта прямая инициализация списка тоже компилируется?

A a;
B b{ a };

Я не смог найти никакой формулировки в списке инициализация с указанием того, что компилятор должен попытаться преобразовать A в B в этом случае.Рассматривается только это разрешение перегрузки для конструкторов:

Если предыдущий этап не приводит к совпадению, все конструкторы T участвуют в разрешении перегрузки для набора аргументов, который состоит из элементов фигурной скобкиinit-list, с ограничением, что разрешены только не сужающие преобразования

Однако в этом случае конструктор копирования удаляется, поэтому не должен ли он быть выбран разрешением перегрузки?

1 Ответ

0 голосов
/ 26 октября 2018

Это CWG 2327 .Вы правы в отношении стандарта, но некоторые компиляторы дополнительно рассматривают функции преобразования и в этом контексте - потому что это действительно имеет смысл.

...