5

I found a piece of C-ish C++ code and asked myself the (slightly academic) question, what implicit type conversions happen here to arrive at the bool that if requires?

int val;
if( (std::cin >> val) == 0 )
    ...

I got this far:

  • std::cin >> val returns (a ref to) cin, thus istream&
  • Therefore == receives cin and 0 as operands, i.e. istream and int

I don't think there is a bool operator==(istream&, int) available (nor the respective member function in istream), so is there a conversion involved?


Just to be clear, the programmers intention was to check if the input was a success, i.e. should have written if(!(std::cin >> val)).

curiousguy
  • 8,038
  • 2
  • 40
  • 58
towi
  • 21,587
  • 28
  • 106
  • 187
  • The return type is `istream&`, not `istream`. The latter would slice the actual object to a pretty-much useless object. – Pete Becker Jun 09 '13 at 17:18
  • @PeteBecker Of course. I noticed that too. I thought it wasn't worth correcting in a sentence-like text, but now I will. Thanks. – towi Jun 09 '13 at 21:07
  • Please tell us if `int i = cin;` compiles for you. – curiousguy Jun 16 '13 at 16:32
  • @curiousguy Why should it? Do you mean because `operator bool()` is defined and that one converts to `int` implicitly? Hrmm... I dont think that will work. Also, I am interested in the *Standard* not a specific implementation, which can be buggy. I think in ´[ios.overview]` (27.5.5.1) you can see that there is no `operator int()` defined on `ios_base`, and I suppose not on other stream classes. So, the question remains, will the compiler choose a different `explicit` conversion operator (`bool`) then I asked for (`int`)? – towi Jun 16 '13 at 20:16
  • @towi The iostream part of the std evolved significantly (not in the general concepts, basic stuff, but in many technicalities). Your iostream implementation may be out of date. Also, let's be honest: *I am also asking out of curiosity*. – curiousguy Jun 16 '13 at 20:53

2 Answers2

1

I don't think there is a bool operator==(istream&, int) available [...] so is there a conversion involved?

Indeed. There is a conversion operator to bool that returns true if no errors occurred, and false otherwise.

Per paragraph 27.5.5.4/1 of the C++11 Standard:

explicit operator bool() const;

1 Returns: !fail().

So the expression (cin >> val) gives you back a (reference to) cin, which is the left operand of ==. The right operand is 0.

Now cin can be converted to bool, and that allows the comparison with 0. In other words, your if statement is equivalent to:

if (!(std::cin >> val))
{
    // ...
}
Community
  • 1
  • 1
Andy Prowl
  • 124,023
  • 23
  • 387
  • 451
  • Yeah, I know. But does this imply that `cin` ins converted to `bool`, `0` is converted to `bool` and then `operator==(bool,bool)` is called? – towi Jun 09 '13 at 13:47
  • @towi: `cin` is converted to `bool`, `val` is not an operand of `==`. The operands of `==` are `cin` and `0` – Andy Prowl Jun 09 '13 at 13:48
  • Yes, I meant `0`, not `val` as operands to `==`. My mistake. I will update the question. It doesn't change my issue, since both are `int`. – towi Jun 09 '13 at 13:51
  • 1
    @towi: `cin` can be converted to `bool`, and that allows a comparison with `int`. I edited my answer to clarify this. – Andy Prowl Jun 09 '13 at 13:55
  • Only to make later reads be able to follow us: After your 2nd edit of your answer you nailed my question. Thanks. I could now remove my other comments :-) – towi Jun 09 '13 at 13:56
  • "equivalent to `if (!(std::cin >> val))`? What about `bool istream::operator!()`? I think the latter version calls `operator!` and the first version calls `operator bool()`. This means they are not equivalent, but have the same effect, right? – towi Jun 09 '13 at 14:00
  • @towi: Equivalent in the sense that the Standard specifies that `operator bool()` should return `!fail()`, while `operator !` should return `fail()`. – Andy Prowl Jun 09 '13 at 14:03
  • Lets call that "similar", then. (I know, I am being academic again). – towi Jun 09 '13 at 14:32
  • @towi: I know what you mean, but "similar" is not a good adjective here. Those two forms will have the exact same output in any situations. To me, that means they are equivalent. – Andy Prowl Jun 09 '13 at 14:41
  • @towi: Does this answer your question? – Andy Prowl Jun 10 '13 at 14:42
  • It does, Herse the checkmark. I disagree on the "similar" vs "equivalent" term, but that's a discussion for another day. – towi Jun 10 '13 at 21:29
  • "_Your assumption is incorrect_" The assumption **is** correct. There is no `operator==(istream&, int)` prototype (or pseudo-prototype) defined anywhere. – curiousguy Jun 16 '13 at 02:14
  • @curiousguy: You're right. I must have thought of something else when I was writing that part of the answer, because later on it is clear that I am supporting what the OP says. Sorry for the confusion and thank you for pointing out. Now I understand why I got downvoted, and it makes sense. Thank you – Andy Prowl Jun 16 '13 at 02:20
  • There is no implicit conversion to `bool` and the value is no contextually converted to bool either. – curiousguy Jun 16 '13 at 16:25
  • @curiousguy: Why not? The expression `std::cin >> val` evaluates to `std::cin` – Andy Prowl Jun 16 '13 at 16:27
  • Is there an implicit conversion from `std::cin` to `bool`? No. Is the expression contextually converted to `bool`? No. – curiousguy Jun 16 '13 at 16:29
0

I believe the code as written is ill-formed.

If you compile without optimization and output assembly you might be able to see which operator or conversion function is called here:

#include <istream>

void f(std::istream &is)
{
    is==0;
}
curiousguy
  • 8,038
  • 2
  • 40
  • 58