Создание вектора движущихся объектов - PullRequest
0 голосов
/ 20 сентября 2018

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

class SomeClass
{
private:
    const std::unique_ptr<Base> foo;

public:
    template <typename T>
    inline explicit SomeClass(T&& derived) noexcept
     : foo(std::make_unique<T>(derived))
    {
        static_assert(std::is_base_of<Base, T>::value);
    }
};

Объект класса может быть создан без проблем, когда мне требуется только один экземпляр:

class Derived : public Base
{
    // ...
};

Derived bar(...);
SomeClass baz(std::move(bar));

// Or

SomeClass baz(Derived(...));

Однако я не могу установить (или передать) любые объекты типа SomeClass в std::vector<SomeClass>.

std::vector<SomeClass> vec;

Derived bar(...);
vec.emplace_back(std::move(bar)); // Does not work.

vec.emplace_back(Derived(...));   // Does not work.

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

Пожалуйста, не могли бы вы также объяснить, как вещи могут быть измененычтобы разрешить построение std::vector<SomeClass>?

Я предполагаю, что, поскольку аргументы конструктора передаются при перемещении, они не передаются полностью в конструктор в методе emplace_back.

1 Ответ

0 голосов
/ 20 сентября 2018

std::vector::emplace_back предъявляет следующие требования к value_type:

Требования к типу

- T (тип элемента контейнера) должен удовлетворять требованиям MoveInsertable и EmplaceConstructible.

const член класса неявно удаляет конструктор перемещения, т.е. SomeClass не является MoveInsertable из-заconst std::unique_ptr<Base> foo.

Решение: удалить const из foo.

struct Base {};
struct Derived : public Base {};

class SomeClass
{
private:
    std::unique_ptr<Base> foo;

public:
    template <typename T>
    inline explicit SomeClass(T&& derived)
        noexcept(std::is_nothrow_constructible_v<decltype(foo), T&&>) // (1)
     : foo(std::make_unique<T>(std::forward<T>(derived))) // (2)
    {
        static_assert(std::is_base_of<Base, T>::value);
    }
};

int main()
{
    std::vector<SomeClass> vec;

    Derived bar{};
    vec.emplace_back(std::move(bar));

    vec.emplace_back(Derived{}); 
}

Живой пример .

В качестве примечания,Я бы предложил сделать noexcept условным в зависимости от std::is_nothrow_constructible (1) и передать std::forward<T>(derived) в std::make_unique, чтобы использовать ссылку переадресации (2).

...