Предположим, у меня есть класс с конструктором удаленных копий:
struct NoCopy
{
NoCopy(int) {}
NoCopy(const NoCopy &) = delete;
};
Я использую этот класс в другом классе:
struct Aggregate
{
NoCopy nc;
};
Но когда я пытаюсь использовать агрегатную инициализацию
int main()
{
Aggregate a{3};
}
Компилятор выдает следующую ошибку:
error: use of deleted function ‘NoCopy::NoCopy(const NoCopy&)’
Почему для инициализации агрегата требуются конструкторы копирования членов класса? Агрегирует ли инициализация все элементы, используя конструкторы копирования?
Правильный синтаксис для того, что вы хотите:
Aggregate a{{3}};
Это обеспечивает инициализатор для NoCopy
член. Без доп {}
компилятор должен выполнить преобразование из int
в NoCopy
(что он с радостью делает через неявный конструктор), а затем использует это для создания nc
, Обычно это происходит как конструкция перемещения, но, удалив копию ctor, вы также эффективно удалили конструктор перемещения.
Проще подумать об этом NoCopy
имел конструктор значения, принимающий два аргумента вместо одного:
struct NoCopy {
NoCopy(int, int);
};
Теперь, если вы написали
Aggregate a{1, 2};
это будет означать, что 1
используется для инициализации nc
а также 2
используется для инициализации чего-то еще (ошибка времени компиляции). Вы должны были бы добавить дополнительные {}
чтобы это имело смысл
Aggregate a{{1, 2}};
Третий способ заключается в рассмотрении вызова функции:
struct NoCopy {
NoCopy(int) {}
NoCopy(const NoCopy &) = delete;
};
void fun(NoCopy) { }
int main() {
fun(1); // wrong
fun({1}); // right
}
в // wrong
версия, временная NoCopy
Объект строится на месте вызова с использованием NoCopy(int)
конструктор. Затем это временное значение передается по значению в fun
, но с тех пор NoCopy
не копируется, не получается.
в // right
версия, которую вы предоставляете список инициализатора для аргумента, который будет создан. Копии не сделаны.
Других решений пока нет …