1

以下のコードでclass Bは、メンバー class の配列が含まれていますclass A
B::Aには 1 つのメンバーboolと 1 つのメンバーがありstd::threadます。
以下のコードは正常にコンパイルされます。

// 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.

$

std::mutex をB::A導入すると、次のコンパイル エラーが発生するのはなぜですか?

// 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;
     ^~~~~

コンパイル エラーを正しく理解していれば、B::Aを明示的に構築しないと のインスタンスを作成できないと不平を言っていますB::A::mutex_。しかし、これが本当なら、なぜこれが必要なのか理解できませstd::mutexん: 以下に示すように、デフォルトのコンストラクターがあるため、コンストラクター引数は必要ありません:

// main.cpp
#include <mutex>

int main( int argc, char* argv[] ) {
  std::mutex mutex[10];

  return 0;
}

上記のコンパイル エラーの性質と、適切な修正方法を教えてください。


更新: @Jarod42 と @chris は、これがコンパイラのバグであることを発見したようです。誰かがこのバグの性質を説明できるかどうかを尋ねる質問を更新しています.オブジェクト要素のメンバー配列を初期化することは、とても単純で基本的なことのようです. このバグを引き起こすオブジェクトの種類とその理由は? これが普遍的/簡単に再現可能な問題になるとは想像できません...?


更新:あまり良くない回避策はB::A::A、空のコンストラクターを作成B::A::b_し、右辺値で初期化することです。:(

// 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
$
4

1 に答える 1