質問: ご覧くださりありがとうございます。 threadクラス及び関数オブジェクトの学習をしております。 下記コードをコンパイルしたら一部エラーが出ました。 ``` #include #include using namespace std; void foo() { printf("mainとは別スレッドで実行されています\n"); } struct bar1 { void operator() (const string& msg) const { printf("%sが渡されました\n",msg.c_str()); } }; struct bar2 { void operator() () { printf("引数なしです\n"); } }; int main() { thread th1(foo); thread th2(bar1(), "An argument"); thread th3(bar2()); th1.join(); th2.join(); th3.join(); return 0; } ``` エラーは以下のようにth3についてです。 __ main.cpp:25:13: warning: parentheses were disambiguated as a function declaration [-Wvexing-parse] thread th3(bar2()); ^~~~~~~~ main.cpp:25:14: note: add a pair of parentheses to declare a variable thread th3(bar2()); ^ ( ) main.cpp:28:6: error: member reference base type 'std::__1::thread (bar2 (*)())' is not a structure or union th3.join(); __ bar2のインスタンスを作ってそれをthread引数に渡せば回避できることは把握しております。 ただ、 **thread th2(bar1(), "An argument");** が通るのに **thread th3(bar2());** が通らないのがなんだか釈然としません。(上記エラーの意味もわかりません) 何が起きていてのエラーなのか、もしわかればC++11の理解が進み大変助かります。 ご存知の方がいらっしゃれば是非ご教示お願いいたします
回答: こんにちは。 initializer listの解説に記載されている下記が原因と思います。 > > C++0xでは、()の代わりに、{}も使えるようになった。どちらも、同じ意味である。ただし、()を使った場合、以下のようなことはできない。 > > > // これは、関数のプロトタイプ宣言。 > > // 引数を取らず、Foo型の戻り値を返す、wrongという名前の関数の宣言。 > > // Foo wrong(void) > > Foo wrong() ; > > > `'std::__1::thread (bar2 (*)())' is not a structure or union`のメッセージをみると、`thread th3(bar2());`を、bar2を返却する関数ポインタを引数とし、threadを返却する関数the3()の宣言と解釈しているのだと思います。 > > thread th3{bar2()}; > > > と修正すればコンパイル通りました。 th2については`"An argument"`のお陰でそのような誤解の余地がないと言うことだと思います。 コンパイラの開発者はこの問題を把握していて、できるだけプログラマの意図を汲み取ろうとしているのではないでしょうか?