Thread: How does std::cin return a bool value?

  1. #1
    Registered User
    Join Date
    Sep 2018
    Posts
    217

    How does std::cin return a bool value?

    How does std::cin return a bool value?
    For instance you can write
    Code:
     if(std::cin) { ... }
    to check the fail state of std::cin. But how does that work, if std::cin is an object of istream?

    Also how do std::cout << "blah" << "blah"; and std::cin >> var >> var2; return bool values? The insertion operator must return ostream object so that cascading works right..

    Can I do something similar with my user-defined class?

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by Nwb
    How does std::cin return a bool value?
    There is an explicit conversion function to bool. Prior to C++11, there was a conversion function to void* instead, i.e., a non-null pointer was returned for true and a null pointer returned for false.

    Quote Originally Posted by Nwb
    Can I do something similar with my user-defined class?
    Yes, e.g.,
    Code:
    class X
    {
    public:
        // ...
    
        explicit operator bool() const
        {
            return n != 0;
        }
    private:
        int n;
    };
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #3
    Registered User
    Join Date
    Sep 2018
    Posts
    217
    Why do we use the keyword 'explicit'? Also can we define this operator for user-defined types too like 'explicit operator Matrix()' or is it just for primitive types?
    So when inside a conditional an object undergoes implicit conversion to bool if possible, cool.

  4. #4
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by Nwb
    Why do we use the keyword 'explicit'? Also can we define this operator for user-defined types too like 'explicit operator Matrix()' or is it just for primitive types?
    You might want to read an article on the topic, e.g., user-defined conversion.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  5. #5
    Registered User
    Join Date
    Sep 2018
    Posts
    217
    Oh okay so something like int var = Foo(5); would be an implicit conversion from Foo to int (if int opeartor is defined, and not explicit). Whereas inside a conditional is considered as explicit conversion from Foo to bool.

    Thanks a lot laserlight

  6. #6
    Registered User
    Join Date
    Sep 2018
    Posts
    217
    Here:
    Code:
    Foo var;
        bool val{ var };
    The compiler will convert var to type bool implicitly. But the compiler is only supposed to look for implicit conversions when '=' is used right.. so only when bool val = var; is written.

    From Bjarne's Tour of C++:

    Code:
    int i1 = 7.2;
    Code:
    //i1 becomes 7 
    int i2 {7.2};//error : floating-point to integer conversion
    int i3 = {7.2};//error : floating-point to integer conversion (the = is redundant)


    But
    Code:
    int i2 {7.2};
    doesn't give me an error!

  7. #7
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by Nwb
    But
    Code:
    int i2 {7.2};
    doesn't give me an error!
    What compiler (including version) and compile options did you use?

    You say there was no error; was there a warning?
    Last edited by laserlight; 02-26-2019 at 05:01 AM.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  8. #8
    Registered User
    Join Date
    Sep 2018
    Posts
    217
    Okay it gives me a compiling error, sorry my bad.

    Back to this:
    Code:
        Foo var;
        int val{ var };
    Suppose we have an operator
    Code:
        operator bool() const {
            return true;
        }
    That should be invalid right? Because implicit conversions are allowed only with the '=' initializing (i.e int val = var; )?

  9. #9
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Write a program to test your hypothesis. If you have questions concerning what you observed, remember to post your test program too.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  10. #10
    Registered User
    Join Date
    Sep 2018
    Posts
    217
    Code:
    #include <iostream>
    
    void print(bool) {
        std::cout << "called";
    }
    
    class Foo {
    public:
    
        operator bool() const {
            return true;
        }
    };
    
    int main() {
        
        Foo var;
        int val{ var };
        std::cout << val;
    
    
        system("pause");
    }
    Code:
    int val{ var };
    should not have compiled because
    Code:
    int val{ constructor arg };
    does not make implicit conversions unlike
    Code:
    int val = constructor arg;
    Just like how we saw
    Code:
    int i2 { 7. 2 };
    was illegal.

  11. #11
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by Nwb
    But the compiler is only supposed to look for implicit conversions when '=' is used right.. so only when bool val = var; is written.
    No, if the form, known as copy initialisation:
    Code:
    T1 x = y;
    is legal where y is of some other type T2, then we say that there is an implicit conversion from T2 to T1 (i.e., objects of type T2 can be implicitly converted to be of type T1), but this doesn't mean that the implicit conversion cannot happen in other contexts, e.g., x could be a function parameter and y a function argument, in which case there would still be an implicit conversion.

    Quote Originally Posted by Nwb
    Code:
    int val{ var };
    should not have compiled because
    Code:
    int val{ constructor arg };
    does not make implicit conversions unlike
    Code:
    int val = constructor arg;
    Formally, how it goes is like this:
    • Going through the semantics of initialisers, we see that the initialiser is a (non-parenthesized) braced-init-list, hence the object (i.e., val) is list-initialized.
    • This is list initialisation in which the initialiser list has a single element, so the object is initialised from that
      element.
    • Going through the semantics of initialisers, we see that this element, as an initialiser, falls under the "remaining copy-initialization cases" for class types in which a user-defined conversion function can be applied. That it is copy initialisation means that this is an implicit conversion.


    Quote Originally Posted by Nwb
    Just like how we saw
    Code:
    int i2 { 7. 2 };
    was illegal.
    That is illegal because it is a narrowing conversion (floating point to int, as Stroustrup commented). Narrowing conversions are not allowed for list initialisation, so the implicit conversion that you wrote is allowed because it does not involve a narrowing conversion. Having read the standard for myself, I'm actually rather surprised at what are regarded as narrowing conversions:
    Quote Originally Posted by C++11 Clause 8.5.4 Paragraph 7
    A narrowing conversion is an implicit conversion
    • from a floating-point type to an integer type, or
    • from long double to double or float, or from double to float, except where the source is a constant expression and the actual value after conversion is within the range of values that can be represented (even if it cannot be represented exactly), or
    • from an integer type or unscoped enumeration type to a floating-point type, except where the source is a constant expression and the actual value after conversion will fit into the target type and will produce the original value when converted back to the original type, or
    • from an integer type or unscoped enumeration type to an integer type that cannot represent all the values of the original type, except where the source is a constant expression and the actual value after conversion will fit into the target type and will produce the original value when converted back to the original type.
    The first and last ones are pretty obvious and should be well known, but the middle two are less obvious and don't necessarily turn up if you were to experiment, e.g.,
    Code:
    double x{2};
    does not result in a narrowing conversion, but:
    Code:
    int y{2};
    double x{y};
    results in a narrowing conversion. In fact, g++ 7.3 only reports a warning for the latter.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  12. #12
    Registered User
    Join Date
    Sep 2018
    Posts
    217
    Code:
    #include <iostream>
    
    struct Foo {
    
        std::ostream& operator <<  (int) {
            return std::cout;
        }
    };
    
    int main() {
        
        Foo var;
    
        if (var << 5) {
            std::cout << "true";
        }
    
        std::cin.get();
    }
    So the condition (var << 5) probably depends on the success of the operation. But can I modify it so that (var << 5) will return false even with some other conditions that are defined by me? Some exceptions that are defined by me?

  13. #13
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by Nwb
    So the condition (var << 5) probably depends on the success of the operation.
    As in whether var << 5 evaluates to true or false in a boolean context? It depends on the current error state of std::cout... and that makes it absurd. Why on earth would var << 5 depend on std::cout? If your intent is to return a bool, then overload the operator to return a bool.

    Quote Originally Posted by Nwb
    But can I modify it so that (var << 5) will return false even with some other conditions that are defined by me? Some exceptions that are defined by me?
    You can do anything you want. What var << 5 means is entirely up to you: you can make it print "hello world!" if the int argument is even and "goodbye world!" if the int argument is odd if you want. You can decide that the numbers 4 and 13 are evil, so if the int argument was either of the two, you throw an exception. But what I'm saying is that for your purposes, returning a std::ostream doesn't seem to make much sense here... but if you really wanted, I imagine you could have a private std::ostream object that you somehow triggered the error state and then returned it, but honestly that is a whole lot of nonsense when the operator<< could be overloaded to return a bool.

    Even if you overloaded operator<< for std::ostream instead, std::cout << var technically can still do anything you want, just that conventionally you should define the overload such that it will output var in some format to std::cout, and then return that ostream, i.e., cout in this case.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 7
    Last Post: 10-04-2018, 03:39 PM
  2. Replies: 5
    Last Post: 03-11-2014, 02:43 PM
  3. bool function always seems to return true
    By The Doctor in forum C++ Programming
    Replies: 1
    Last Post: 10-22-2012, 11:07 PM
  4. BOOL bool ? unresolved external symbol
    By xwielder in forum C Programming
    Replies: 6
    Last Post: 05-20-2008, 08:39 AM
  5. Interesting: bool != BOOL
    By lightatdawn in forum A Brief History of Cprogramming.com
    Replies: 5
    Last Post: 01-09-2002, 11:09 AM

Tags for this Thread