I have a non-moveable base class that I want to construct using a factory function. If it's just a member, and not a base, everything works fine:
#include <utility>
#include <mutex>
struct NonMoveable
{
std::mutex m;
};
struct WithMember
{
NonMoveable v;
template <typename Factory>
WithMember(Factory f) : v{f()} { }
};
WithMember with_member()
{
return WithMember{[] { return NonMoveable{}; }};
}
But if the NonMoveable
is a base, the compiler complains about the implicitly deleted copy constructor:
#include <utility>
#include <mutex>
struct NonMoveable
{
std::mutex m;
};
struct WithBase
: NonMoveable
{
template <typename Factory>
WithBase(Factory f) : NonMoveable(f()) { }
};
WithBase with_base()
{
return WithBase{[] { return NonMoveable{}; }};
}
Here's the error:
<source>:20:27: error: call to implicitly-deleted copy constructor of 'NonMoveable'
WithBase(Factory f) : NonMoveable(f()) { }
^ ~~~
<source>:30:12: note: in instantiation of function template specialization 'WithBase::WithBase<(lambda at <source>:30:21)>' requested here
return WithBase{[] { return NonMoveable{}; }};
^
<source>:6:16: note: copy constructor of 'NonMoveable' is implicitly deleted because field 'm' has a deleted copy constructor
std::mutex m;
^
/opt/compiler-explorer/gcc-9.2.0/lib/gcc/x86_64-linux-gnu/9.2.0/../../../../include/c++/9.2.0/bits/std_mutex.h:94:5: note: 'mutex' has been explicitly marked deleted here
mutex(const mutex&) = delete;
^
1 error generated.
Compiler returned: 1
Links to godbolt: https://godbolt.org/z/2PnFsa
I have a feeling this is some obscure rule in the standard. What prevents this from working and is it a good reason to keep things that way?