std::basic_...peratorbool(3)

πŸ“¦ version 2024.07.05, in nixpkgs unstable, opensuse-leap 16.0

πŸ’… std::basic_ios::operatorbool β€” std::basic_ios::operatorbool

okay bestie, this is a page from the C++ Standard Libary manpage set (std::basic_...peratorbool(3)) and it's genuinely one of those little gems that makes C++ loops not suck. let's get into it 🫢

✨ NAME ✨

std::basic_ios::operatorbool β€” literally std::basic_ios::operatorbool, no notes, that's the whole name πŸ’€

🌸 Synopsis 🌸

operator /* unspecified-boolean-type */() const; (1) (until C++11)
explicit operator bool() const;                  (2) (since C++11)

so what does it do? it checks whether the stream has no errors. that's it, that's the vibe check πŸ‘‘

  1. Returns a value that evaluates to false in a boolean context if fail() returns true, otherwise returns a value that evaluates to true in a boolean context.
  2. Returns true if the stream has no errors and is ready for I/O operations. Specifically, returns !fail().

This operator makes it possible to use streams and functions that return references to streams as loop conditions, which is how you get the idiomatic C++ input loops like

while (stream >> value) {...}

or

while (std::getline(stream, string)) {...}

and those loops only run the body if the input operation actually succeeded. so clean, so readable, obsessed πŸ’–

πŸŽ€ Parameters πŸŽ€

(none) β€” not a single parameter, she takes nothing and still delivers 😌

πŸ¦‹ Return value πŸ¦‹

  1. A value that evaluates to true in a boolean context if the stream has no errors, a value that evaluates to false in a boolean context otherwise.
  2. true if the stream has no errors, false otherwise.

⭐ Notes ⭐

This conversion can be used in contexts where a bool is expected (e.g. an if condition). However, implicit conversions (e.g. to int) that can occur with bool are not allowed. (that's the whole point, bestie β€” no sneaky int conversions 🚫)

okay little history lesson because it's actually juicy:

In C++98, operator bool could not be provided directly due to the safe bool problem. The initial solution in C++98 is to provide operator void*, which returns a null pointer if fail() returns true or a non-null pointer otherwise. It is replaced by the resolution of LWG issue 468, which allows Safe Bool idiom to be applied.
Since C++11, conversion functions can be explicit. The resolution of LWG issue 1094 introduced the explicit operator bool and the boolean conversion is now safe. slay πŸ’…

πŸ”₯ Example πŸ”₯

// Run this code

#include <iostream>
#include <sstream>

int main()
{
    std::istringstream s("1 2 3 error");
    int n;

    std::cout << std::boolalpha << "s is " << static_cast<bool>(s) << '\n';
    while (s >> n)
        std::cout << n << '\n';
    std::cout << "s is " << static_cast<bool>(s) << '\n';
}

🌈 Output:

s is true
1
2
3
s is false

see how it reads the three numbers, hits the word error, the stream goes bad, and the loop just stops? no cap, that's the whole magic trick 🧚


πŸ‘‘ Defect reports πŸ‘‘

The following behavior-changing defect reports were applied retroactively to previously published C++ standards. (yes, they went back and fixed history, main character energy fr fr)

  • LWG 468 β€” Applied to: C++98 β€” Behavior as published: operator void* was provided β€” Correct behavior: a conversion function to an unspecified boolean type is provided instead

πŸ’œ See also πŸ’œ

The following table shows the value of basic_ios accessors (good(), fail(), etc.) for all possible combinations of ios_base::iostate flags β€” so here's the whole grid, every single row, no skipping πŸ™ˆ

  • ios_base::iostate flags: eofbit false, failbit false, badbit false β†’ good() true, fail() false, bad() false, eof() false, operator bool true, operator! false
  • ios_base::iostate flags: eofbit false, failbit false, badbit true β†’ good() false, fail() true, bad() true, eof() false, operator bool false, operator! true
  • ios_base::iostate flags: eofbit false, failbit true, badbit false β†’ good() false, fail() true, bad() false, eof() false, operator bool false, operator! true
  • ios_base::iostate flags: eofbit false, failbit true, badbit true β†’ good() false, fail() true, bad() true, eof() false, operator bool false, operator! true
  • ios_base::iostate flags: eofbit true, failbit false, badbit false β†’ good() false, fail() false, bad() false, eof() true, operator bool true, operator! false
  • ios_base::iostate flags: eofbit true, failbit false, badbit true β†’ good() false, fail() true, bad() true, eof() true, operator bool false, operator! true
  • ios_base::iostate flags: eofbit true, failbit true, badbit false β†’ good() false, fail() true, bad() false, eof() true, operator bool false, operator! true
  • ios_base::iostate flags: eofbit true, failbit true, badbit true β†’ good() false, fail() true, bad() true, eof() true, operator bool false, operator! true
tiny heads up bestie: eofbit being set with failbit clear still gives you operator bool == true β€” she's fine, she's just at the end of the file 🌸

and that's the page! πŸŽ€ huge shoutout to http://cppreference.com, version 2024.06.10, for keeping the lore alive β€” this one's dated 2024.06.10 too, so it's fresh. go write some while (stream >> x) loops and text me how it goes πŸ’–βœ¨πŸ¦‹

πŸ“¦ where this page comes from