I have a class which contains a constructor which moves an object during its construction:
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);
}
};
The an object of the class can be constructed without issue when I require only a single instance:
class Derived : public Base
{
// ...
};
Derived bar(...);
SomeClass baz(std::move(bar));
// Or
SomeClass baz(Derived(...));
However I am unable to emplace (or push) any objects of type SomeClass to a 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.
Please could you explain why objects can not be emplaced? I thought that the perfect forwarding that emplace_back
used would allow construction of an instance of SomeClass
inplace in the same way that a single instance could be constructed.
Please could you also explain how things might be modified to allow construction of a std::vector<SomeClass>
?
My guess is that as constructor arguments are passed by move, then they are not being forwarded all the way to the constructor within the emplace_back
method.
std::vector::emplace_back
imposes the following requirements onvalue_type
:A
const
member of a class implicitly deletes move constructor, i.e.SomeClass
is notMoveInsertable
because ofconst std::unique_ptr<Base> foo
.Solution: remove
const
fromfoo
.Live example.
As a side note, I would suggest to make
noexcept
conditional depending onstd::is_nothrow_constructible
(1) and passstd::forward<T>(derived)
tostd::make_unique
to utilise forwarding reference (2).