Инициализация массива C ++ 11 не копируемым типом с явным конструктором

У меня есть (сторонний) класс, который не подлежит копированию. Я хотел бы инициализировать их массив. Вот моя лучшая попытка:

#include <array>

class Thing
{
public:
explicit Thing(int) {}
Thing(const Thing&) = delete;
};

int main()
{
std::array<Thing, 1> things{{{100}}}; // error here
};

GCC 4.7.2 говорит:

ошибка: преобразование в ‘std :: array :: value_type
{aka Thing} ’из списка инициализаторов будет использовать явный конструктор
«Вещь :: Thing (интермедиат)»

Хорошо, но это именно то, что я хочу — использовать явный конструктор. Как я могу выразить это? Если я на самом деле вызываю конструктор сам, то получаю ошибку об удалении конструктора копирования. И я не могу использовать std::move() потому что вещь не подвижна (и я не могу ее изменить).

Единственная альтернатива, которую я нашел, https://stackoverflow.com/a/15962814/4323 но это нежелательно, потому что это куча лишнего кода, плюс мне нужно приводить «хранилище» везде, где я его использую (или хранить отдельный указатель на него, что добавляет косвенность, которую я не хочу).

Я хочу решение, которое дает максимальную производительность при использовании вещей без большого количества отвратительного шаблона.

7

Решение

И снова C ++ 17 гарантированная копия elision приходит на помощь: выражение как Thing{100} больше никогда создает объект, но просто указывает как какой-то другой объект (ваш элемент массива) должен быть создан.

1

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

Я попытался добавить ctor по умолчанию и оператор присваивания перемещения, немного изменил инициализацию и он компилируется:

#include <array>

class Thing
{
public:
explicit Thing(int) {}
Thing(const Thing&) = delete;
Thing(Thing&&) = default;
Thing& operator=(Thing&&) = default;
};

int main()
{
std::array<Thing, 1> things {{ Thing(100) }}; // error gone
}

РЕДАКТИРОВАТЬ: я пропустил «стороннюю» часть. Извините, если это не поможет 🙂

1

Вы можете использовать std::vector:

std::vector<Thing> things;
things.reserve(1);
things.emplace_back(100);

или только для одного элемента boost::optional:

boost::optional<Thing> thing;
thing.emplace(100);
-2
По вопросам рекламы [email protected]