C ++ 17 добавить класс с конструктором удаленных копий в std :: vector во время компиляции - PullRequest
1 голос
/ 07 ноября 2019

Ниже приведен класс, который я определил с помощью конструктора удаленных копий и оператора назначения копирования. Это единственное предположение, которое необходимо сделать.

class MyClass
{
    public:
    explicit MyClass(int i) : i(i) {}

    MyClass(const MyClass&) = delete;
    MyClass& operator=(const MyClass&) = delete;

    MyClass(MyClass&& other) :
        i(std::move(other.i))
        {}  

    MyClass& operator=(MyClass&& other) {
        i = std::move(other.i);
        return *this;
    }   

    private:
    int i;
};

Цель состоит в том, чтобы добавить мой класс в std :: vector во время компиляции.

int main()
{
    std::vector<MyClass> v{MyClass{0}, MyClass{1}, MyClass{2}};

    return 0;
}

Мой компиляторсообщая мне, что STL требует использования моего конструктора удаленных копий MyClass::MyClass(const MyClass&), но есть ли способ обойти это?

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

int main()
{
    std::vector<MyClass> v;
    v.emplace_back(MyClass{0});
    v.emplace_back(MyClass{1});
    v.emplace_back(MyClass{2});

    return 0;
}

1 Ответ

5 голосов
/ 07 ноября 2019

Мой компилятор говорит мне, что STL требует использования моего конструктора удаленных копий MyClass::MyClass(const MyClass&), но есть ли способ обойти это?

Нет, вы не можете.

initializer_list создает для вас скрытый массив, который объявляется const и оценивается примерно так:

// pseudo code
const MyClass __arr[3] = { MyClass(1), MyClass(2), MyClass(3) };
std::vector<MyClass> v{ std::initializer_list<MyClass>{ __arr, __arr + 2 } }; 

Если вы хотите избежать копирования, вам придется придерживатьсяна emplace_back как вы сказали.

Мне уже известен возможный способ добавления значений во время выполнения ...

Кстати, пример, который вы привели не - правильный способ использования emplace_back:

std::vector<MyClass> v;
v.emplace_back(MyClass{0});
v.emplace_back(MyClass{1});
v.emplace_back(MyClass{2});

Вы все еще создаете MyClass и затем перемещаете его в v, что является довольно распространенной ошибкой, когдаиспользуя emplace -иш функции.

Что вы действительно хотели сделать, это, вероятно, следующим образом:

v.reserve(3);
v.emplace_back(0);
v.emplace_back(1);
v.emplace_back(2);

Таким образом вы избегаете случайно вызова конструктора перемещения и просто создаете объект вправильное место только один раз без движения и без копии .

Цель состоит в том, чтобы добавить мой класс в std::vector во время компиляции.

Если вы хотите создать массив во время компиляции, используйте std::array. std::array специально разработан для этой цели:

std::array<MyClass, 3> v = { 1, 2, 3 };
...