Why can't I return std::getline's as-if-boolean result?
Asked Answered
H

1

33

A standard idiom is

while(std::getline(ifstream, str))
    ...

So if that works, why can't I say

bool getval(std::string &val)
{
    ...

    std::ifstream infile(filename);

    ...

    return std::getline(infile, val);
}

g++ says "cannot convert 'std::basic_istream<char>' to 'bool' in return".

Is the Boolean context of a return statement in a bool-valued function somehow different from the Boolean context of while(), such that the magic conversion that std::basic_istream performs in one context doesn't work in the other?


Addendum: There's apparently some version and perhaps language standard dependency here. I got the aforementioned error with g++ 8.3.0. But I don't get it with gcc 4.6.3, or LLVM (clang) 9.0.0.

Hermelindahermeneutic answered 14/3, 2022 at 22:41 Comment(4)
hmm, works with a cast, but not implicitly - paging c++ level 5 wizardsVermouth
return !!std::getline(infile, val); would be an optionUraeus
Precious few questions pique my interest as much as this one, good one. I look forward to seeing the answers since the compiler has all information needed to know it has to end up as a boolean.Seumas
OT: @TedLyngmo Well, maybe it would be better something more "explicit": return std::getline(infile, val).good();Sporule
T
49

The boolean conversion operator for std::basic_istream is explicit. This means that instances of the type will not implicitly become a bool but can be converted to one explicitly, for instance by typing bool(infile).

Explicit boolean conversion operators are considered for conditional statements, i.e. the expression parts of if, while etc. More info about contextual conversions here.

However, a return statement will not consider the explicit conversion operators or constructors. So you have to explicitly convert that to a boolean for a return.

Tamqrah answered 14/3, 2022 at 22:48 Comment(13)
so 'explicit' conversions sometimes arentVermouth
Thank you. explicit is one of those diminishing-return nuances that my poor old brain doesn't consider important enough to learn, but slapping bool(...) around my std::getline() call seems to be working.Hermelindahermeneutic
'when initializing a new object of type T2, including return statement in a function returning T2;' - that's in the docs, why does it not apply here?Seumas
@SteveSummit there's the old !! trick too. operand of ! counts as "explicit" conversion to boolMandate
@paxdiablo, that is only for implicit conversions. In C++ those will be constructors and operators not marked explicit.Tamqrah
@Mandate Ted Lyngmo suggested that, too. That's probably what I would have tried next, without Fatih's answer. But the question here was "Why doesn't this work?", not "What can I use instead?".Hermelindahermeneutic
Sorry, damn ipad posted my comment early. The rest was that it also has 'when the expression is used in an if statement or a loop (T2 is bool).'. Surely that covers the while case? Or am I missing something?Seumas
In other words, it looks like 'while' should also not consider explicit converters. ???Seumas
Never mind, just followed your link for the contextual conversions. The stuff I found seems to state where implicit conversion happens rather than where explicit conversions cannot. Your other link clarifies the distinction. Good answer.Seumas
@Mandate "operand of ! counts as "explicit" conversion to bool" - except in this case, since istream has an operator! implemented.Belak
Instead of using the C-style cast bool(...) shouldn't we use static_cast<bool>(...) instead?Cliffcliffes
@infinitezero, static_cast debate aside, I think the C-style cast would be (bool)..., AFAIK bool(...) is C++-only.Tamqrah
Took me some searching but the bool(...) syntax is a form of en.cppreference.com/w/cpp/language/explicit_cast (point (2)): it translates directly to a C-style cast and is only usable for 1 word types. So, yeah for both those reasons I do think a static_cast seems more appropriate.Inaccessible

© 2022 - 2025 — McMap. All rights reserved.