In the code below, class B
contains an array of member class class A
.
B::A
has one member bool
and one member std::thread
.
The code below compiles fine:
// main.cpp
#include <mutex>
#include <thread>
class B {
public:
B();
private:
class A {
public:
A( const bool& b ) : b_( b ) {}
bool b_;
std::thread thread_;
} a_[2];
};
B::B() : a_{ { false }, { false } } { }
int main( int argc, char* argv[] ) {
B b;
return 0;
}
$ g++ --version && g++ -g ./main.cpp
g++ (Debian 6.3.0-18+deb9u1) 6.3.0 20170516
Copyright (C) 2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$
Why does introducing a std::mutex to B::A
introduce the following compile error?
// main.cpp
#include <mutex>
#include <thread>
class B {
public:
B();
private:
class A {
public:
A( const bool& b ) : b_( b ) {}
bool b_;
std::mutex mutex_; // I break compilation!
std::thread thread_;
} a_[2];
};
B::B() : a_{ { false }, { false } } { }
int main( int argc, char* argv[] ) {
B b;
return 0;
}
$ g++ -g ./main.cpp
./main.cpp: In constructor ‘B::B()’:
./main.cpp:21:35: error: use of deleted function ‘B::A::A(B::A&&)’
B::B() : a_{ { false }, { false } } { }
^
./main.cpp:11:9: note: ‘B::A::A(B::A&&)’ is implicitly deleted because the default definition would be ill-formed:
class A {
^
./main.cpp:11:9: error: use of deleted function ‘std::mutex::mutex(const std::mutex&)’
In file included from /usr/include/c++/6/mutex:44:0,
from ./main.cpp:2:
/usr/include/c++/6/bits/std_mutex.h:97:5: note: declared here
mutex(const mutex&) = delete;
^~~~~
If I correctly understand the compile error, it's complaining that an instance of B::A
cannot be created without explicit construction of B::A::mutex_
. But if this is true, I don't understand why this should be necessary: std::mutex
has a default constructor, so doesn't need any constructor arguments, as demonstrated below:
// main.cpp
#include <mutex>
int main( int argc, char* argv[] ) {
std::mutex mutex[10];
return 0;
}
Please help me understand the nature of the above compile error, and what an appropriate fix might be.
Update: @Jarod42 and @chris seem to have discovered this is a compiler bug. I'm updating the question to ask if anyone could explain the nature of this bug -- initiaizing member array-of-object elements seems like such a simple and foundational thing. What type of objects trigger this bug and why? I can't imagine this could be a universal/easily reproducible problem...?
Update: A not-great workaround seems to be making B::A::A
an empty constructor and initializing B::A::b_
with an rvalue. :(
// main.cpp
#include <mutex>
#include <thread>
class B {
public:
B();
private:
class A {
public:
A() : b_( false ) {}
bool b_;
std::mutex mutex_;
std::thread thread_;
} a_[2];
};
B::B() { }
int main( int argc, char* argv[] ) {
B b;
return 0;
}
$ g++ -g ./main.cpp
$
question from:
https://stackoverflow.com/questions/65947612/why-does-introducing-stdmutex-to-member-class-generate-this-compile-error