我有一个类,其中包含一个构造函数,该构造函数会在构造对象时移动它:
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>
吗?
我的猜测是,由于构造函数参数是通过move传递的,因此它们不会在emplace_back
方法中一直传递到构造函数。
答案 0 :(得分:2)
std::vector::emplace_back
对value_type
施加了以下要求:
类型要求
-
T
(容器的元素类型)必须满足MoveInsertable
和EmplaceConstructible
的要求。
类的const
成员隐式删除move构造函数,即由于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
(1)使std::is_nothrow_constructible
为条件,并将std::forward<T>(derived)
传递给std::make_unique
以使用转发参考(2)。