Совокупная инициализация класса с некопируемым членом

Предположим, у меня есть класс с конструктором удаленных копий:

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&)’

Почему для инициализации агрегата требуются конструкторы копирования членов класса? Агрегирует ли инициализация все элементы, используя конструкторы копирования?

3

Решение

Правильный синтаксис для того, что вы хотите:

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 версия, которую вы предоставляете список инициализатора для аргумента, который будет создан. Копии не сделаны.

7

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

Других решений пока нет …

По вопросам рекламы [email protected]