Hello,
The current implementation of boost::noncopyable prevents derived classes
from declaring a defaulted move constructor:
#include
struct S : boost::noncopyable
{
S(S&&) = default;
};
S f();
int main()
{
S s = f();
}
Errors (with gcc trunk):
test3.cpp: In function 'int main()':
test3.cpp:12:13: error: use of deleted function 'S::S(S&&)'
test3.cpp:5:5: error: 'S::S(S&&)' is implicitly deleted because the default definition would be ill-formed:
/usr/include/boost/noncopyable.hpp:27:7: error: 'boost::noncopyable_::noncopyable::noncopyable(const boost::noncopyable_::noncopyable&)' is private
test3.cpp:5:5: error: within this context
The problem is that the default move constructor for S tries to move the
noncopyable base subobject, but noncopyable does not have a move
constructor (one isn't generated implicitly because a user-defined copy
constructor is present). Then it tries to fall back to the noncopyable
copy constructor, but that of course is private.
If we give the definition of the S move constructor explicitly, all is
well because no one is trying to move or copy the noncopyable subobject:
struct S : boost::noncopyable
{
S(S&&) {}
};
However, having to define the move constructor explicitly is annoying and
a maintenance hazard (e.g. if you add a data member, you have to add it
to the move constructor too).
If we modify noncopyable to give it a move constructor, the defaulted
move constructor now works in derived classes.
I think we should either give noncopyable a move constructor, or add a
similar class ("noncopyable_but_movable"? - I'm bad with names) that is
like noncopyable but also has a move constructor.
Thoughts?
Regards,
Nate.