Ответ 1
Два поведения изменились с С++ 11.
-
Изменено поведение std:: basic_ios:: operator bool.
operator void*() const; (1) (until C++11) explicit operator bool() const; (2) (since C++11)
Обратите внимание, что С++ 11
operator bool()
объявляется какexplicit
; но дляif ((ss >> f) == false)
,ss
(т.е. возвращаемое значение(ss >> f)
) должно быть неявным преобразованным вbool
(для сравнения сfalse
), что недопустимо. -
Изменено определение константы нулевого указателя.
До того, как С++ 11
operator void*()
можно было бы использовать, а это неexplicit
(до С++ 11 нет такого явного пользовательского преобразования), а до С++ 11 константа нулевого указателя определяется как:интегральное постоянное выражение rvalue целочисленного типа, которое вычисляется до нуля (до С++ 11)
что означает, что
false
может использоваться как константа нулевого указателя. Таким образом,ss
может быть неявно преобразован вvoid*
, а затем сравниваться сfalse
(как нулевой указатель).Из С++ 11 константа нулевого указателя определяется как:
целочисленный литерал со значением 0 или значение типа
std::nullptr_t
(поскольку С++ 11)пока
false
снова не будет; это не целочисленный литерал.
Итак, из-за этих двух изменений if ((ss >> f) == false)
не будет работать в С++ 11 и более поздних версиях.
С другой стороны, if (!(ss >> f))
работает отлично, потому что std:: basic_ios:: operator! (как до, так и после C + +11).
bool operator!() const;
Возвращает
true
, если в связанном потоке произошла ошибка. В частности, возвращаетtrue
, если badbit или failbit установлены вrdstate()
.
BTW: Поскольку С++ 11, даже без std::basic_ios::operator!
, explicit operator bool() const
также мог бы сделать if (!(ss >> f))
хорошо, потому что в контексте контекстное преобразование, explicit
учитывается пользовательское преобразование; т.е. ss
может быть контекстно преобразован в bool
для operators !
.