Копировать инициализацию с оператором преобразования - PullRequest
4 голосов
/ 31 марта 2020

Есть код в copy_initialization

struct A 
{
  operator int() { return 12;}
};

struct B 
{
  B(int) {}
};
int main()
{
 ....
    A a;
    B b0 = 12;
//    B b1 = a; //< error: conversion from 'A' to non-scalar type 'B' requested
    B b2{a};        // < identical, calling A::operator int(), then B::B(int)
    B b3 = {a};     // <
    auto b4 = B{a}; // <
}

Теперь вопрос

  • Как работает прямая инициализация в случае b2? Может ли оператор прямой инициализации преобразовать вызов?
  • Почему при инициализации копирования происходит сбой для b1? Неявно A следует преобразовать в int, и можно вызвать конструктор B.
  • b3 также является инициализацией копирования, но это работает. Почему так?

1 Ответ

6 голосов
/ 31 марта 2020

Это очень просто: неявная конвертируемость (для пользовательских типов) не является транзитивным свойством в C ++. То есть, хотя A конвертируется в int, а int конвертируется в B, это означает, что не само по себе означает, что A конвертируется в B. Не существует допустимой последовательности неявного преобразования из A в B, поэтому A не может быть преобразовано в B.

Для инициализации копирования требуется неявная конвертируемость между типом выражения инициализации и типом инициализируется. Поскольку A не конвертируется в B, b1 не компилируется.

Каждый раз, когда вы видите {} как часть инициализации, подобной этой, это означает, что объект, к которому он применяется, в соответствии с go некоторая форма инициализации списка, которая отличается от других форм инициализации.

b2 не выполняет "прямую инициализацию". Он выполняет прямую список инициализацию, которая является одной из двух форм инициализации списка. Правила инициализации списка, в этом случае, в конечном итоге сводятся к использованию разрешения перегрузки для набора конструкторов для B. Существует конструктор B, который можно вызывать с помощью A, поскольку этот вызов может происходить посредством неявного преобразования int в *1034*.

b3 not "copy" инициализация "; это копия список инициализация, которая абсолютно не связана с «копией инициализации». Copy-list-initialization идентична прямой-list-initialization точно с двумя исключениями, ни одно из которых не применимо к этому случаю. Так что он делает то же самое, что и b2.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...