つい最近知ってちょっと衝撃を受けたことについて.
非const参照パラメータが指定されている関数の項に右辺値(リテラルもしくは関数から返される一時オブジェクト)を指定できないのは有名.
void f( int &i ) { ..... } int g() { return 1; } int main() { f( g() ); // ダメ. C++ の言語規格では認められていない }
これは非constなテンプレートパラメータが指定された関数の項でも同じ.
template< class T > void f( T &i ) { ..... } int g() { return 1; } int main() { f( g() ); // 同じくダメ. }
これは比較的良く知られている(のか?)規格で,別にいまさらこれに驚いたわけじゃない.
ところが右辺値の型が const 修飾されていると,それがこの非 const な参照テンプレートパラメータを指定された項で受けられることにいまさら気が付いた.
template< class T > void f( T &i ) { ..... } int const g() // 戻り値が const 修飾されていることに注意 { return 1; } int main() { f( g() ); // O.K. f のテンプレートパラメータ T が int const と // 推論されるので f が一時オブジェクトを受けられる. }
これに驚いた.
Boost.Lambda において生成される(一時オブジェクトである)ラムダ式オブジェクトに対する The forwarding problem をどう解決しているのか不思議といえば不思議だったのだけれど,なるほど,どうりでわざわざラムダ式オブジェクトのオブジェクトジェネレータの戻り値を const にしているわけですにゃ〜.ようやくあの Boost.Lambda の実装の const 修飾の意味を理解したつもりになった.そんにゃ冬の日の夜.