そんな大げさに言わなくても … (オマケ付き)
38.4.5.3 ユーザ定義の操作子
….(略)….
さて、この宣言によって、<<と()の組合せが、単一の3項演算子に統合されることに注意しよう。cout<<sci4{d}は、実際の処理を実行する前に、ostreamと書式と値を、単一の関数に集約する。
38.5 ストリーム反復子
原文:
Note that these declarations make the combination of << and () into a ternary operator;
cout<<sci4{d} collects the ostream, the format, and the value into a single function before doing any real computation.
試訳:
これらの宣言が << と () の組み合わせを三項演算子にすることに注意しよう。cout<<sci4{d} は、実際の処理を実行する前に、ostreamと書式と値を単一の関数(オブジェクト)にまとめる。
考察:
Form sci4; という宣言は見当たらないけどどこかにあるとして(名前から見て sci4.scientific().precision(4) も実行されているだろう)、sci4のForm::operator()を引数dと共に呼び出す(sci4{d})ことで新たに値dと結び付けられたBound_form型のインスタンスを作り出し、それを cout::operator<<(ostream&,const Bound_form&) に渡す、という流れ。
sci4{d} は sci4(d) と書いても同じ。
Form sci4;
Bound_form bf { sci4(d) };
cout << bf;
と分けて書いても同じ(dはどこかで宣言されているものとして)。
オマケの補足: なぜsci4{d} と書くことで Form::operator() が呼び出されるのか?
ぱっと見不思議な書き方で一瞬ミスプリントじゃないかと思ったくらいですが、これはどうも、{}の初期化リストからコンパイラがinitializer_list<>を自動生成するのと、作成されたinitialize_listの要素が一個の場合は引数一個のoperator()関数の呼び出しに変換されるようで、そのため、引数一個の場合に限りこのような書き方が出来るみたいです。(違うかも、実は自信ないです)
引数が無い場合や二個ある場合は{}を使った書き方はコンパイルエラーになってしまいます。operator()の呼び出しで汎用的に()の代わりに{}が使える訳ではない模様。