创建移动构造对象的向量
Creating vector of move-constructed objects
我有一个 class,其中包含一个在构造过程中移动对象的构造函数:
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 的对象:
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>
?
我的猜测是,由于构造函数参数是通过 move 传递的,因此它们不会一直转发到 emplace_back
方法中的构造函数。
std::vector::emplace_back
对 value_type
提出以下要求:
Type requirements
-T
(the container's element type) must meet the requirements of MoveInsertable
and EmplaceConstructible
.
class 的 const
成员隐式删除移动构造函数,即 SomeClass
不是 MoveInsertable
因为 const std::unique_ptr<Base> foo
.
解决方案:从 foo
.
中删除 const
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{});
}
作为旁注,我建议根据 std::is_nothrow_constructible
(1) 使 noexcept
成为条件,并将 std::forward<T>(derived)
传递给 std::make_unique
以利用转发引用 (2 ).
我有一个 class,其中包含一个在构造过程中移动对象的构造函数:
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 的对象:
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>
?
我的猜测是,由于构造函数参数是通过 move 传递的,因此它们不会一直转发到 emplace_back
方法中的构造函数。
std::vector::emplace_back
对 value_type
提出以下要求:
Type requirements
-
T
(the container's element type) must meet the requirements ofMoveInsertable
andEmplaceConstructible
.
class 的 const
成员隐式删除移动构造函数,即 SomeClass
不是 MoveInsertable
因为 const std::unique_ptr<Base> foo
.
解决方案:从 foo
.
const
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{});
}
作为旁注,我建议根据 std::is_nothrow_constructible
(1) 使 noexcept
成为条件,并将 std::forward<T>(derived)
传递给 std::make_unique
以利用转发引用 (2 ).