Почему это использование emplace_back с удаленным конструктором копии не работает?

У меня есть тип, из которого я удалил конструктор копирования, и хотел бы иметь vector этого типа, поэтому мне нужно создать все элементы с помощью emplace_back. Но для emplace_back требуется конструктор копирования, поскольку компилятор дает предупреждение о невозможности создания экземпляра emplace_back, поскольку конструктор копирования был удален. Зачем нужен конструктор копирования? Я думал, что цель emplace_back заключалась в создании vector без копирования чего-либо. Могу ли я даже vector объектов, у которых нет конструктора копирования?

class MyType {
public:
    MyType(std::array<double, 6> a) {}
    MyType(const MyType& that) = delete;
};

int main() {
    std::vector<MyType> v;
    std::array<double, 6> a = {1,2,3,4,5,6};
    v.emplace_back(a);
}

Компилятор - clang/llvm.

Ответы

Ответ 2

Чтобы иметь возможность вызвать emplace_back, ваш тип должен быть EmplaceConstructible или MoveInsertible. Вам нужно предоставить конструктор перемещения для вашего класса, если вы удалили конструктор копии. (Проверьте этот для требований emplace_back)

 MyType(MyType &&a) {/*code*/} //move constructor

Ответ 3

Если вы попытаетесь запустить этот код:

// Example program
#include <iostream>
#include <string>
#include <array>
#include <vector>
class MyType {
public:
    MyType(std::array<double, 6> a) {
        std::cout<< "constructed from array\n";
        }
    MyType(const MyType& that){
          std::cout<< "copy\n";
    }

    MyType(MyType&& that){
          std::cout<< "move\n";
    }
};

int main() {
    std::vector<MyType> v;
    std::array<double, 6> a = {1,2,3,4,5,6};
    v.emplace_back(a);
}

Вы получите следующий результат:

построенный из массива

Live Demo

Понятно, что вызывается только constructor из std::Array. Поэтому нет необходимости в copy constructor. Но в то же время, если вы deleted copy constructor, компилятор поднимет ошибку (по крайней мере, на двух компиляторах я попробовал сначала second). Я думаю, что некоторые компиляторы будут проверять существование copy constructor при использовании emplace_back, даже если это не нужно в этом практическом случае, а другие - нет. Я не знаю, что здесь стандартно (какой компилятор прав или не прав).