std :: список типа «только для перемещения»: невозможно вставить в std :: vector в VC ++ - PullRequest
3 голосов
/ 16 июня 2019

В VC ++ 2019 я не могу emplace_back (rvalue) list типа только для перемещения.

#include <vector>
#include <list>

struct A
{
    A(A&&) {}
};

using ListOfA = std::list<A>;

int main()
{
    std::vector<ListOfA> v;

    // Build error in VC++ 2019
    // No error in Clang and GCC C++11 - C++2a
    v.emplace_back(std::move(ListOfA()));
}

Попытка встроить VC ++ 2019 приводит к следующей ошибке компиляции:

'A::A(const A &)': attempting to reference a deleted function

Ясно, что VC ++ пытается создать экземпляр (lvalue) конструктора копирования для A, который (правильно) не существует, потому что я явно определил один из конструкторов для A.

Я думаю, что было бы правильным создать экземпляр list на месте в vector, переместившись из другого list - то есть класс list имеет move constructor , который, я думаю, должен просто заставить новый list вступать во владение элементами в (перемещенном) list, не требуя копий.

Фактически,используя Wandbox, тот же код создается и выполняется без ошибок с использованием GCC и Clang.

Может кто-нибудь объяснить, почему этот код не компилируется в VC ++ 2019?Есть ли у меня неправильное понимание - есть ли на самом деле веская причина, по которой конструктор копирования (lvalue) создается компилятором VC ++ в приведенном выше коде?


Примечание

Та же ошибка возникает в VC ++, когда std::move(...) отсутствует;то есть такая же ошибка возникает с этой строкой:

v.emplace_back(ListOfA());

1 Ответ

3 голосов
/ 16 июня 2019

MSVC использует конструктор копирования std::list, потому что его конструктор перемещения выбрасывает.Во время перераспределения, если конструктор перемещения бросает, std::vector не может обеспечить строгую гарантию исключений, как того требует стандарт.

В вашем случае вектор не имеет никакого элемента перед перераспределением, поэтому кажется, что конструктор копированияне вызывается, но это не означает, что конструктор копирования не нужен.

std::list в libstdc ++ и libc ++ имеет noexcept конструктор перемещения.Это разрешено, но не требуется стандартом.

...