1

我有一个包含构造函数的类,该构造函数在构造过程中移动对象:

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与可以构造单个实例相同的方式构造就地实例。

请您还可以解释一下如何修改事物以允许构建 astd::vector<SomeClass>吗?

我的猜测是,由于构造函数参数是通过 move 传递的,因此它们不会一直转发到方法中的构造函数emplace_back

4

1 回答 1

2

std::vector::emplace_back对 施加以下要求value_type

类型要求

- T(容器的元素类型)必须满足 和 的MoveInsertable要求EmplaceConstructible

类的const成员隐式删除移动构造函数,即SomeClass不是MoveInsertable因为const std::unique_ptr<Base> foo.

解决方案:constfoo.

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)。

于 2018-09-20T00:42:08.850 回答