[2013/8/3に作成した内部メモ] まず、やはり非explicitな変換コンストラクタを大量に作成するとambigousエラーが 発生しやすくなる。引数一つのコンストラクタはexplicitにしたい。 そうすると、is_convertibleでは内部型として受け入れられるかどうか判定できなくなってしまう。 また、is_explicitly_convertibleまたはis_constructibleは時期尚早。 そこで、convertibleは自前で処理し、コンストラクタの有無に依らないことにする。 具体的には、共通にincludeするconvert.hppで、 namespace kv { // C is convertible to T or not template struct convertible { static const bool value = boost::is_convertible::value; }; // C is acceptable as numeric constant of T template struct acceptable_n; // C is acceptable as string constant of T template struct acceptable_s; } のように、元となる構造体を作成。これを部分特殊化してカスタマイズしていく。 例えばintervalでは、 template class interval; template struct convertible > { static const bool value = convertible::value || boost::is_same >::value || boost::is_convertible::value; }; template struct acceptable_n > { static const bool value = convertible::value && (! boost::is_conve rtible::value); }; template struct acceptable_s > { static const bool value = boost::is_convertible::value; }; の通り。 「Cからintervalへは、CからTへ変換可能か、Cがintervalか、Cが文字列の場合に変換可能」 「intervalへの数値定数としては、Tへ変換可能か文字列が受け入れられる」 「intervalへの文字定数としては、文字列が受け入れられる」 と読む。 explicitにしたので、acceptable_nな代入演算子は作成する。 hoge a = 1.のように初期化時に=を使えないことに気を付ける。 (hoge a(1.), hoge a = hoge(1.), hoge a; hoge = 1. なら問題ない) 内部の書き方は、全てacceptable_{n,s}を使うことにしたので、将来ポリシーが 変わったときも容易に変更可能。 また、enable_ifを全てenable_if_cにして、将来のC++11への以降に備える。