2021年1月28日星期四

Why does introducing std::mutex to member class generate this compile error?

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  $  
https://stackoverflow.com/questions/65947612/why-does-introducing-stdmutex-to-member-class-generate-this-compile-error January 29, 2021 at 09:33AM

没有评论:

发表评论