2

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?

Alexander Kondratskiy
  • 4,156
  • 2
  • 30
  • 51

0 Answers0