[解決済み] コンパイラによって呼び出されるキャスト演算子が異なる
質問
次のような短いC++プログラムを考えてみましょう。
#include <iostream>
class B {
public:
operator bool() const {
return false;
}
};
class B2 : public B {
public:
operator int() {
return 5;
}
};
int main() {
B2 b;
std::cout << std::boolalpha << (bool)b << std::endl;
}
異なるコンパイラでコンパイルすると、様々な結果が得られます。Clang 3.4 と GCC 4.4.7 では、次のように表示されます。
true
と表示され、Visual Studio 2013では
false
で異なるキャスト演算子を呼び出していることを意味します。
(bool)b
. 規格上、どちらが正しい動作なのでしょうか?
私の理解では
operator bool()
は変換を必要としませんが
operator int()
は変換が必要ですが
int
から
bool
に変換されるので、コンパイラは最初のものを選ぶはずです。は
const
はそれで何かをするのでしょうか、コンパイラはconst-conversionをよりquot;expensive"と見なすのでしょうか。
もし私が
const
を削除すると、すべてのコンパイラが等しく
false
を出力します。
一方、2つのクラスを一緒にすると(両方の演算子が同じクラスになる)、3つのコンパイラとも、出力として
true
を出力します。
どのように解決するのですか?
規格に記載されています。
派生クラス内の変換関数は、2つの関数が同じ型に変換しない限り、基底クラス内の変換関数を隠さない。
§12.3 [class.conv]を参照してください。
ということは
operator bool
で隠れないということです。
operator int
.
規格に記載されています。
オーバーロードの解決中、暗黙のオブジェクト引数は他の引数と区別がつかない。
§13.3.3.1 [over.match.func]を参照してください。
この場合の "暗黙のオブジェクト引数" は次のとおりです。
b
であり、型は
B2 &
.
operator bool
が必要です。
const B2 &
を必要とするので、コンパイラは const を
b
を呼び出すために
operator bool
. これによって -- 他のすべての条件が同じであれば --
operator int
の方がより良い一致となります。
規格では
static_cast
(この例では C スタイルのキャストが実行されています) に変換して
T
に変換することができます (この例では
int
) の場合。
宣言
T t(e);
は整形式で、ある発明された一時変数に対してt
.§5.2.9節 [expr.static.cast]を参照してください。
そのため
int
に変換される可能性があります。
bool
に、そして
bool
は同様に
bool
.
規格に記載されています。
の変換関数は
S
とその基底クラスの変換関数が考慮される。の中に隠されていないそれらの非明示的な変換関数が考慮される。S
の中に隠されておらず,型T
またはタイプに変換可能なタイプT
に変換できる型であれば、標準的な変換シーケンスで が候補となる関数です。§13.3.1.5節 [over.match.conv]を参照してください。
つまり、オーバーロード・セットは
operator int
と
operator bool
. 他の条件がすべて同じなら
operator int
の方がより良くマッチします(constnessを追加する必要がないので)。 したがって
operator int
が選択されるべきです。
標準では、(おそらく直感に反して)一旦オーバーロード集合に追加されると、(上記で確立されたように)戻り値の型(すなわち、これらの演算子が変換する型)を考慮しないことに注意。ただし、それらのうちの一方の引数の変換シーケンスが他方の引数の変換シーケンスより優れている場合(これは、恒常性のためにこの例ではそうである)である。
規格では
これらの定義を考えると、実行可能な関数F1は、すべての引数iについて、ICSi(F1)がICSi(F2)より悪い変換列でなければ、別の実行可能な関数F2より良い関数であると定義され、そして、次に
- ある引数 j に対して、ICSj(F1) は ICSj(F2) よりも良い変換シーケンスであるか、または、そうでなければ。
- の場合、コンテキストはユーザ定義変換による初期化であり、F1の戻り型から目的型(すなわち、初期化される実体の型)への標準変換シーケンスは、F2の戻り型から目的型への標準変換シーケンスより良い変換シーケンスである。
§13.3.3節 [over.match.best]の項参照。
この場合、引数は1つだけです(暗黙的な
this
パラメータ) のみです。 の変換シーケンスは
B2 &
=>
B2 &
(を呼び出すには
operator int
) よりも優れています。
B2 &
=>
const B2 &
(を呼び出すには
operator bool
)であるため
operator int
に直接変換されないという事実を気にすることなく、 オーバーロードのセットから選択されます。
bool
.
関連
-
[解決済み】Visual Studio 2015で「非標準の構文; '&'を使用してメンバーへのポインターを作成します」エラー
-
[解決済み】C++エラーです。"配列は中括弧で囲まれたイニシャライザーで初期化する必要がある"
-
[解決済み】文字列関数で'char const*'のインスタンスを投げた後に呼び出されるterminate [閉店].
-
[解決済み】関数名の前に期待されるイニシャライザー
-
[解決済み] 非常に基本的なC++プログラムの問題 - バイナリ式への無効なオペランド
-
[解決済み】エラー:free(): 次のサイズが無効です(fast)。
-
[解決済み] C++の規格では、初期化されていないboolがプログラムをクラッシュさせることは可能ですか?
-
[解決済み】C/C++の"-->"演算子とは何ですか?
-
[解決済み] Intel CPU の _mm_popcnt_u64 で、32 ビットのループカウンターを 64 ビットに置き換えると、パフォーマンスが著しく低下します。
-
[解決済み] カンマ付きの三項演算子は、なぜ真の場合、1つの式しか評価しないのですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】Visual Studio 2015で「非標準の構文; '&'を使用してメンバーへのポインターを作成します」エラー
-
[解決済み】LLVMで暗黙のうちに削除されたコピーコンストラクタの呼び出し
-
[解決済み】Visual Studio 2015で「非標準の構文。'&'を使用してメンバーへのポインターを作成します」エラー
-
[解決済み】IntelliSense:オブジェクトに、メンバー関数と互換性のない型修飾子がある
-
[解決済み】オブジェクト引数のない非静的メンバ関数の呼び出し コンパイラーエラー
-
[解決済み】C++の余分な資格エラー
-
[解決済み] gdbを使用してもデバッグシンボルが見つからない
-
[解決済み] to_string は std のメンバーではない、と g++ が言っている (mingw)
-
[解決済み】システムが指定されたファイルを見つけられませんでした。
-
[解決済み] 現在のCまたはC++の標準文書はどこにありますか?