6

代入演算子の複数のオーバーロードを次のように定義しています。

Foo.h

class Foo
{
private:
    bool my_bool;
    int my_int;
    std::string my_string;
public:
    Foo& operator= (bool value);
    Foo& operator= (int value);
    Foo& operator= (const std::string& value);
};

Foo.cpp

// Assignment Operators.
Foo& Foo::operator= (bool value) {my_bool = value; return *this;}
Foo& Foo::operator= (int value) {my_int = value; return *this;}
Foo& Foo::operator= (const std::string& value) {my_string = value; return *this;}

そして、これが私のmain.cppです(マークされたコメントを参照してくださいSURPRISE):

Foo boolFoo;
Foo intFoo;
Foo stringFoo;

// Reassign values via appropriate assignment operator.
boolFoo = true;                // works...assigned as bool
intFoo = 42;                   // works...assigned as int
stringFoo = "i_am_a_string";   // SURPRISE...assigned as bool, not string

std::string s = "i_am_a_string";
stringFoo = s;                 // works...assigned as string

// works...but awkward
stringFoo = static_cast<std::string>("i_am_a_string");

質問:キャストされていない文字列リテラルがブールコンテキストで評価されている理由を誰かに教えてもらえますか?

4

2 に答える 2

11

C ++標準では、13.3章で過負荷解決ルールが定義されています。

13.3.3.2暗黙の変換シーケンスのランク付け[over.ics.rank]

2暗黙の変換シーケンスの基本形式を比較する場合(13.3.3.1で定義)

—標準の変換シーケンス(13.3.3.1.1)は、ユーザー定義の変換シーケンスまたは省略記号の変換シーケンスよりも優れた変換シーケンスであり、

—ユーザー定義の変換シーケンス(13.3.3.1.2)は、省略記号の変換シーケンス(13.3.3.1.3)よりも優れた変換シーケンスです。

これは、コンパイラが文字列リテラルから、boolまたはint使用可能な場合は標準の変換シーケンスを優先することを意味します。さて、どの標準変換が関連していますか?あなたの場合、これら2つは関連しています。

4.2配列からポインタへの変換[conv.array]

1「NTの配列」または「Tの未知の境界の配列」タイプの左辺値または右辺値は、「Tへのポインター」タイプのprvalueに変換できます。結果は、配列の最初の要素へのポインターです。

この変換により、タイプがである文字列リテラルが。const char[N]に変換されconst char*ます。2つ目は次のとおりです。

4.12ブール変換[conv.bool]

1算術、スコープなしの列挙、ポインター、またはメンバー型へのポインターのprvalueは、タイプのprvalueに変換できますbool。ゼロ値、ヌルポインター値、またはヌルメンバーポインター値はfalse;に変換されます。その他の値はに変換されtrueます。タイプのprvalueは、タイプのstd::nullptr_tprvalueに変換できますbool。結果の値はfalseです。

これが、ポインタがに変換される理由boolです。標準の変換シーケンスが存在するため、へのユーザー定義の変換std::stringは使用されません。

問題を解決するためにconst char*、呼び出しをconst std::string&オーバーロードに転送する別のオーバーロードバージョンを追加することをお勧めします。

于 2013-02-22T19:48:55.307 に答える
4

ダニエルは正しいです。

簡単にstd::string言えば、これは組み込み型ではないため、魔法のような優遇措置は受けていません。そして、残念ながら、のような文字列リテラルの型は"hi world"isではなく 、 「ユーザー定義」型よりもstd::string組み込み型に簡単に変換できるポインター型です。boolstd::string

基本的に、答えは次のとおりです。C++ へようこそ。

はい、わかっています。これは標準ライブラリからのものであり、いいえ、問題ではありません。

于 2013-02-22T20:22:07.063 に答える