Подтвердить что ты не робот

Как std:: cin возвращает bool и сам в одно и то же время?

Я читаю книгу на С++, в которой говорится, что если я использую оператор → , он возвращает объект в левой части оператора, поэтому в этом примере

std::cin >> value1;

код возвращает std::cin.

Но если я это сделаю

while(std::cin >> value1)

Мой код будет в цикле до тех пор, пока не будет ошибка std::cin, так что это должно означать, что оператор возвращает bool, который является истинным, когда std::cin не сбой, а false, когда std::cin терпит неудачу.

Что это такое?

4b9b3361

Ответ 1

[...], так что это должно означать, что оператор возвращает bool [...]

Нет, он возвращает std::cin (по ссылке). Причина, по которой работает while(std::cin >> value);, состоит в том, что std::istream (тип std::cin) имеет оператор преобразования.

Оператор преобразования в принципе позволяет неявному (если он не помечен explicit) классу быть преобразованным в заданный тип. В этом случае std::istream определяет свой operator bool для возврата, произошла ли ошибка (обычно failbit);

[std::ios_base::operator bool()]

Возвращает true, если поток не имеет ошибок и готов к операциям ввода-вывода. В частности, возвращает !fail().


explicit operator bool() const;

Обратите внимание, что хотя оператор explicit (который не должен допускать неявные преобразования, такие как if (std::cin);), квалификатор игнорируется при использовании в контексте, который требует bool, например if, while и циклы for. Это исключения, но не правила.

Вот пример:

if (std::cin >> value);  //OK, a 'std::istream' can be converted into a 'bool', which 
                         //therefore happens implicitly, without the need to cast it: 

if (static_cast<bool>(std::cin >> value)); //Unnecessary

bool b = std::cin >> value;  //Error!! 'operator bool' is marked explicit (see above), so 
                             //we have to call it explicitly:

bool b = static_cast<bool>(std::cin >> value); //OK, 'operator bool' is called explicitly

Ответ 2

std::istream (класс, который std::cin является объектом) имеет следующую функцию-член:

explicit operator bool() const;

Он возвращает false, если объект находится в состоянии ошибки, и true в противном случае. Вот почему работает конструкция while(std::cin >> value1). Перед С++ 11 вместо этого была использована эта неявная функция:

operator void*() const;

Что вернуло нулевой указатель, если объект находился в состоянии ошибки, служащей той же цели.

Ответ 3

Операции с потоками возвращают ссылку на поток.

Итак, не bool.

Вы можете вставить результат в условие if по той же причине, что вы можете сделать это:

void* ptr = foo();
if (ptr) { /*...*/ }

И, если на то пошло, это:

int x = foo();
if (x) { /*...*/ }

Оба ptr и x здесь могут быть преобразованы в bool для использования в условии. В случае std::cin преобразование достигается с помощью operator bool() в классе std::ostream, который был явно (предназначен для каламбуров) для этой точной задачи.

Ответ 4

std::cin имеет тип std::istream (который является просто a typedef std::basic_istream<char>)

Если вы видите разные перегруженные operator>> для basic_istream, все они возвращают ссылку на basic_istream. Итак, выясняется, что operator>> здесь не возвращает bool, а вместо этого возвращает "std::cin". Вы не увидите никаких operator>>, возвращающих значение bool.

Итак, вопрос в том, как он преобразует std::basic_istream в bool?
Ответ: для этой цели вызывается оператор преобразования.

std::basic_istream наследует operator bool() из родительского std::basic_ios

explicit operator bool() const;

что позволяет преобразовать объект std::basic_istream в bool. Нетрудно заметить, что он отмечен как explicit (см. почему он помечен как explicit), и все же он неявно преобразован в bool в if или while.

Ответ на этот вопрос заключается в том, что if или while использует явное преобразование "неявно". (см. этот ответ by @R. Martinho Fernandes). Таким образом, if, while и for являются одним из мест, где это "противоречивое преобразование" в bool происходит неявно.