Std::vector emplace_back() для не копируемых конструктивных объектов

Учитывая эту цитату из en.cppreference.com относительно std::vector::emplace_back

"Добавляет новый элемент в конец контейнера. построенный на месте, то есть операции копирования или перемещения не выполняются. Конструктор элемента называется точно таким же аргументы, которые предоставляются функции."

и следующий образец:

#include <vector>
struct A
{
    A(int){}
    A(A const&) = delete;
};

int main()
{
    std::vector<A> vec;
    vec.emplace_back(1);

    return 0;
}

В строке vec.emplace_back(1); Отчет Visual Studio 2013/GCC:

ошибка C2280: 'A:: A (const A &)': попытка ссылки на удаленную функцию

ошибка: использование удаленной функции "A:: A (const A &)

Правильно ли ошибка? Можете ли вы объяснить мне, почему?

Ответ 1

С++ 11 23.2.1 В таблице 101 указано:

Выражение: a.emplace_back(args)

Тип возврата: void

Семантика операции: добавляет объект типа T, построенный с помощью std::forward<Args>(args).... Требуется: T должно быть EmplaceConstructible в X из args. Для vector, T также должно быть MoveInsertable в X.

Ваш A не выполняет требование MoveInsertable, так как у вас нет конструктора перемещения и есть только конструктор удаленной копии. С контейнером, отличным от std::vector, он работает.

Ответ 2

Как и другие функции, которые увеличивают размер вектора, emplace_back условно перераспределяет вектор (если текущая емкость недостаточно велика). Если это так, то нужно получить существующие элементы из старого массива в новый.

У вашего класса нет конструктора перемещения (некоторые классы имеют сгенерированный компилятором ход, но не этот, потому что вы удалили конструктор копирования). Поэтому код перераспределения должен иметь возможность копировать тип, и он не может.

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