ショート
変換関数operator int()
はconst修飾されていないoperator bool() const
ため、clang overによって選択されますがb
、boolの変換演算子はです。
簡単な理由は、次のように変換b
するときに、(暗黙のオブジェクトパラメータが設定された)過負荷解決の候補関数であるということbool
です。
operator bool (B2 const &);
operator int (B2 &);
b
はconst修飾されていないため、2番目の方がより適切に一致します。
両方の関数が同じ資格(両方const
または両方)を共有している場合operator bool
は、直接変換を提供するため、が選択されます。
キャスト表記による変換、段階的に分析
我々は、ブールのostream挿入([ostream.inserters.arithmetic]あたりとしては、STD :: basic_ostream ::演算子<<(BOOLヴァル))の変換から結果こと値で呼び出されることに同意した場合b
にbool
、我々はその変換に掘ることができます。
1.キャスト表現
ブール値へのbのキャスト
(bool)b
に評価します
static_cast<bool>(b)
に従って C ++ 11、5.4 / 4 [expr.cast]のでconst_cast
(追加またはここでCONST除去しない)は適用されません。
この静的変換は、発明された変数tが適切に形成されている場合、C ++ 11、5.2.9 / 4 [expr.static.cast]に従って許可bool t(b);
されます。このようなステートメントは、次のように直接初期化と呼ばれます。、C ++ 11、8.5 / 15 [dcl.init]ます。
2.直接初期化 bool t(b);
最も言及されていない標準段落の条項16は次のように述べています(私の強調):
初期化子のセマンティクスは次のとおりです。宛先タイプは初期化されるオブジェクトまたは参照のタイプであり、ソースタイプは初期化式のタイプです。
[...]
[...]ソースタイプが(おそらくcv修飾された)クラスタイプである場合、変換関数が考慮されます。
該当する変換関数が列挙され、過負荷の解決によって最適なものが選択されます。
2.1どの変換機能が利用できますか?
利用可能な変換関数でありoperator int ()
且つoperator bool() const
としてので12.3 / 5 [class.conv]は、C ++ 11、教えてくれる。
派生クラスの変換関数は、2つの関数が同じ型に変換されない限り、基本クラスの変換関数を非表示にしません。
一方、C ++ 11、13.3.1.5/1 [over.match.conv] :状態
Sとその基本クラスの変換関数が考慮されます。
ここで、Sは変換元のクラスです。
2.2どの変換機能が適用できますか?
C ++ 11、13.3.1.5 / 1 [over.match.conv](私の強調):
1 [...]「cv1T」が初期化されるオブジェクトのタイプであり、「cv S」が初期化式のタイプであり、Sがクラスタイプであると仮定すると、候補関数は次のように選択されます。 Sとその基本クラスの関数が考慮されます。S内に隠されておらず、タイプTまたは標準の変換シーケンスを介してタイプTに変換できるタイプを生成する非明示的な変換関数が候補関数です。
したがって、operator bool () const
内部に隠されておらずB2
、を生成するため、適用可能bool
です。
最後に、標準的な引用に重点を置いた部分は、用いた変換に関連しているoperator int ()
ので、int
標準の変換シーケンスを介してブール値に変換することができるタイプです。からint
への変換bool
はシーケンスではなく、C ++ 11、4.12 / 1 [conv.bool]で許可されている単純な直接変換です。
算術、スコープなしの列挙、ポインター、またはメンバー型へのポインターのprvalueは、bool型のprvalueに変換できます。ゼロ値、ヌルポインター値、またはヌルメンバーポインター値はfalseに変換されます。その他の値はすべてtrueに変換されます。
これは、それoperator int ()
も適用できることを意味します。
2.3どの変換機能が選択されていますか?
適切な変換関数の選択は、過負荷解決(C ++ 11、13.3.1.5 / 1 [over.match.conv])を介して実行されます。
過負荷解決は、呼び出す変換関数を選択するために使用されます。
クラスメンバー関数のオーバーロード解決に関しては、特別な「癖」が1つあります。それは、暗黙的なオブジェクトパラメータです。
あたりのC ++ 11、13.3.1 [over.match.funcs] 、
[...]静的および非静的メンバー関数の両方に暗黙のオブジェクトパラメーターがあります[...]
ここで、非静的メンバー関数のこのパラメーターのタイプは、第4節によると次のとおりです。
ここで、Xは関数がメンバーであるクラスであり、cvはメンバー関数宣言のcv修飾です。
これは、(C ++ 11、13.3.1.5 / 2 [over.match.conv]による)、変換関数による初期化で、
引数リストには、初期化式である1つの引数があります。[注:この引数は、変換関数の暗黙的なオブジェクトパラメーターと比較されます。—エンドノート]
過負荷解決の候補関数は次のとおりです。
operator bool (B2 const &);
operator int (B2 &);
明らかに、operator int ()
変換はタイプの非定数オブジェクトを使用して要求された場合、より良い試合ですB2
ので、operator bool ()
必要な資格変換。
両方の変換関数が同じconst資格を共有している場合、それらの関数の過負荷解決はもはやトリックを行いません。この場合、変換(シーケンス)ランキングが行われます。
3.operator bool ()
両方の変換関数が同じconst資格を共有しているのに、なぜ選択されるのですか?
からB2
への変換bool
は、ユーザー定義の変換シーケンスです(C ++ 11、13.3.3.1.2 / 1 [over.ics.user])。
ユーザー定義の変換シーケンスは、最初の標準変換シーケンス、ユーザー定義の変換、2番目の標準変換シーケンスで構成されます。
[...]ユーザー定義の変換が変換関数によって指定されている場合、最初の標準変換シーケンスは、ソースタイプを変換関数の暗黙的なオブジェクトパラメーターに変換します。
C ++ 11、13.3.3.2 / 3 [over.ics.rank]
[...]は、より良い変換シーケンスとより良い変換の関係に基づいて、暗黙的な変換シーケンスの半順序を定義します。
[...]ユーザー定義の変換シーケンスU1は、同じユーザー定義の変換関数またはコンストラクターまたは集計の初期化を含み、U1の2番目の標準変換シーケンスがより優れている場合、別のユーザー定義の変換シーケンスU2よりも優れた変換シーケンスです。 U2の2番目の標準変換シーケンス。
第二の規格の変換がある場合でoperator bool()
あるbool
とbool
した場合の第二標準変換は、一方(恒等変換)operator int ()
であるint
のbool
ブール変換です。
したがって、operator bool ()
両方の変換関数が同じconst資格を共有している場合は、を使用した変換シーケンスの方が適しています。