boost::variantのgetがメンバじゃない理由

先週名古屋にてBoost.勉強会#5が開催されました.

それとは直接関係ないのですが,行きの電車の中でBoost.Variantの仕様に関して疑問をもってTwitterでつぶやいたところ@cpp_akiraさんより回答をいただいて,それがすごく興味深い内容だったのでそのやりとりをこちらでメモ.

boost::variant<T1,T2,...>のオブジェクトtがあったときにt.get<T1>()と書きたいなぁ,とか…. boost::get<T1>(t)となってるのはどういう意図or理由なんでしょう.
@mrxptn
すずき

@ template限定子が必要になるからです。
@cpp_akira
Faith and Brave

ん?template限定子って何だ…?
ということでググります.
@cpp_akiraさんのブログが最初に出てきました.
http://d.hatena.ne.jp/faith_and_brave/20080128/1201510970

えっ…,こんな構文初めて見た….

で,このことがboost::variantにも影響してて,

@ ありがとうございます,もし書くとすればt.template get<T1>()と書かなくちゃいけなくなってこれはめんどくさい…という認識でいいですか? (こんな構文初めて見ました><;;)
@mrxptn
すずき
@ ですです。テンプレート内でメンバ関数テンプレートを呼ぶときにだけtemplateが必要になって混乱するからですね。
@cpp_akira
Faith and Brave

なるほど.
ライブラリアンの方はよく考えてるんだなー.
「できること」と「するべきこと」は違うってことですね.

仮にメンバとしてgetが実装されていたとしたら,

@ なるほど…そこでうっかりt.get<T1>()と書いてエラーで怒られても間違いなく理解できないですね…
@mrxptn
すずき

つまり,普通にメンバだからつって何も考えず呼び出しコード書いてtemplate限定子ないって怒られても….

とは言っても,

@ まぁでも、Boost.MultiIndexを使ってるとまれによく必要になりますw
@cpp_akira
Faith and Brave

fm...
なるほど.
調べた限りだとまだよくわかんないので,宿題ということで.

で,少しだけ関係あるんじゃないかと勝手に思ってる話.

template限定子は,メンバ関数の実引数から型を推定できないとき…なので,テンプレート化の対象が型じゃなくて値のときは当然問題なくて,Boost.Tupleのgetメソッドは普通にn番目の要素をテンプレート実引数の形で指定できます.

boost::tuple<int, int> t = boost::make_tuple(10, 20);
std::cout << t.get<0>() << std::endl;
std::cout << t.get<1>() << std::endl;
std::cout << t.get<2>() << std::endl;    //compile error!!!!!

ですが,C++0xでのstd::tupleでは,getはグローバルに追い出されました.

std::tuple<int, int> t(10, 20);
std::cout << std::get<0>(t) << std::endl;
std::cout << std::get<1>(t) << std::endl;
std::cout << std::get<2>(t) << std::endl;   //compile error!!!!!

これはさっきのvariantに合わせるための変更なのかなー,などと思っています.
いや,そんなのたぶんディスカッションの記録見れば答えがあるんでしょうけど.

コメントを残す

メールアドレスが公開されることはありません。