質問

I checked the C++11 standard and found the following facts:

  1. std::getline(fin, str) returns a basic_ios object, whose class has a member function explicit operator bool() const;

  2. The class basic_ios doesn't have a member function operator void*() const; as pre-C++11.

So, I think if (getline(fin, str)) {} is not standard conforming. It should be written as

if (bool(getline(fin, str)){}. (However, VC++ 2012 gives a warning on this usage. i.e. force void* to bool)

Am I correct?

役に立ちましたか?

解決 3

David is correct, and here are the quotes to back him up. In §12.3.2/2, the Standard says

A conversion function may be explicit (7.1.2), in which case it is only considered as a user-defined conversion for direct-initialization (8.5). Otherwise, user-defined conversions are not restricted to use in assignments and initializations. [ Example:

class Y { };
struct Z {
    explicit operator Y() const;
};

void h(Z z) {
    Y y1(z); // OK: direct-initialization
    Y y2 = z; // ill-formed: copy-initialization
    Y y3 = (Y)z; // OK: cast notation
}

end example]

Some places where this contextual conversion happens is in the operand to !, the operands to &&, and the condition of an if.

So direct initialisation can make use of explicit conversion operators, and in §4/3,

An expression e can be implicitly converted to a type T if and only if the declaration T t=e; is well-formed, for some invented temporary variable t (8.5). Certain language constructs require that an expression be converted to a Boolean value. An expression e appearing in such a context is said to be contextually converted to bool and is well-formed if and only if the declaration bool t(e); is well-formed, for some invented temporary variable t (8.5)...

So as you can see, the standard specifies as-if direct initialisation for contextual conversions, so that's why explicit conversions work in if conditions.

他のヒント

The code is conforming. The explicit conversion operator to bool will be called when the object is used as a condition automatically. The change in the standard was meant to maintain that same usage while making it a bit safer.

explicit operator bool (and only explicit operator bool) has special language that allows it to be implicitly converted to a bool in certain circumstances. The specification language for this conversion is "contextually converted to bool".

These are the places where the language does boolean testing. The conditional expression used by an if/while/for is "contextually converted to bool". As are the logical operators and the conditional operator (?:).

So while you can't do these:

bool b = std::getline(fin, str);
void func(bool) {}
func(std::getline(fin, str));

You can do these:

while(std::getline(fin, str)) {...}
for(;std::getline(fin, str);) {...}
if(std::getline(fin, str) && somethingElse) {...}
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top