2017-01-10 12 views
11

次のコードはVisual Studio 2008ではコンパイルされますが、Visual Studio 2013以降では失敗します。ストリーム演算子>>をブール値として評価する

std::string str("foo"); 
std::stringstream ss(str); 
float f = 0; 

if ((ss >> f) == false) 
    std::cout << "Parse error\n"; 

エラーメッセージが

エラーC2678ある:バイナリ '==':NOオペレータが見つからないタイプの左手 オペランドをとる 'STD :: basic_istream>'(または存在 受け入れ可能な変換)

はなく、以下のように正常に変更することによって固定されている:

if (!(ss >> f)) 
    std::cout << "Parse error\n"; 

私はこれをよく理解していません。私の質問は、演算子やキャスト、あるいはiosのフラグがストリームの読み取りを最初にブール値として評価できるようにするためのフラグで、operator==が足りないのはなぜですか?

答えて

16

C++ 11以降の2つの動作が変更されました。

  1. std::basic_ios::operator boolの動作が変更されました。

    operator void*() const;   (1) (until C++11) 
    explicit operator bool() const; (2) (since C++11) 
    

    C++ 11 operator bool()explicitとして宣言されているので注意。 if ((ss >> f) == false)の場合、ss(つまり戻り値は(ss >> f))は暗黙的にboolfalseと比較される)に変換する必要がありますが、これは許可されていません。

  2. ヌルポインタ定数の定義が変更されました。

    C++ 11 operator void*()を使用することができ、それはexplicitない(そのようなexplicit user-defined conversionはありませんC++ 11の前)、およびC++ 11 the null pointer constantのように定義される前に前:

    積分定数falseを意味する(C++ 11まで)がゼロ に評価整数タイプ

    の発現右辺値はヌルポインタ定数として使用することができます。したがって、ssは暗黙的にvoid*に変換され、次にNULLポインタとしてfalseと比較されます。 C++ 11から

    、ヌルポインタ定数は、次のように定義される:ゼロ値、またはタイプのprvalueリテラル

    整数std::nullptr_t (以降は、C++ 11)

    falseはもう一度ではありません。それはinteger literalではありません。

この2つの変更のため、if ((ss >> f) == false)はC++ 11以降では機能しません。

一方、if (!(ss >> f))は、std::basic_ios::operator!(両方ともC++ 11の前後)であるため、問題なく動作します。

bool operator!() const; 

エラーが関連するストリーム上で発生している場合trueを返します。 badbitまたはfailbitがrdstate()に設定されている場合は、具体的にはtrueを返します。

BTW

contextual conversionの文脈において、explicitユーザ定義の変換が考えられるため、C++ 11ので、偶数std::basic_ios::operator!ことなく、explicit operator bool() constもよくif (!(ss >> f))作品を作ることができます。すなわちssoperators !の場合にboolに文脈的に変換できます。

+0

「bool」演算子の明示的な変換に関する例外の1つで、 'operator bool'が' explicit'とマークされていても、 'if(foo)'や 'if(!foo)'が機能することがあります。例[ここ](http://coliru.stacked-crooked.com/a/e884a7adaf92a472)。私はこれを**文脈変換**といいます。 [このブログの投稿](http://chris-sharpe.blogspot.ca/2013/07/contextually-converted-to-bool.html)。 – vsoftco

+1

'NULL'は、" the "ヌルポインタ定数ではなく、" nullポインタ定数 "という用語の同義語でもなく、* a *ヌルポインタ定数に展開されるマクロです。 –