Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Visual C++ - call conversion operator on a primitive type explicitly

I was playing around with a class Foo, that defined an implicit operator bool(). I used Foo as a return type for several functions, so I could get an information about what had been done and call the Foo::operator bool() to get whether the operation had performed successfully.

Out of curiosity, I also tried an explicit call of the conversion operator while using Foo:

if(!func().operator bool()) // func returned Foo
    throw std::logic_error("operation was not successful");

That worked fine. Then, I suddenly decided to dump the Foo class and go with simple bool but I forgot to remove .operator bool() call on the function return value. And so I discovered a set of strange behaviors of Visual C++ 12.0 compiler (Visual Studio 2013).


None of the explicit calls of conversion operators to bool are valid in GCC:
request for member ‘operator bool’ in ‘true’, which is of non-class type ‘bool’

Now, the behavior I get with Visual Studio:

#include <iostream>
using std::cout;
using std::endl;

bool func()
{
    return true;
}

int main()
{
    bool b = true.operator bool();
    cout << b << endl; // error C4700: uninitialized local variable 'b' used

    // evaluates to true (probably like b would do if it compiled)
    if(false.operator bool())
        cout << "a" << endl;

    cout << func().operator bool() << endl; // prints nothing

    int m = 10;
    cout << m.operator int() << endl; // prints nothing

    // correctly gives error: left of '.<' must have class/struct/union
    cout << m.operator <(10) << endl;
}

Even the intellisense is right and shows Error: expression must have a class type. Is there an explanation to all this? A bug? An (unwanted) extension? What is it?

like image 606
LogicStuff Avatar asked Apr 22 '15 08:04

LogicStuff


1 Answers

Nice find! The standard definitely makes this ill-formed with a diagnostic required, [expr.ref]:

A postfix expression followed by a dot . or an arrow ->, optionally followed by the keyword template (14.2), and then followed by an id-expression, is a postfix expression. [..] For the first option (dot) the first expression shall have complete class type.

Also, not an extension: Would be one hell of a nonsensical extension. It seems that VC++ implements bool with some internal (class-like?) type:

In Visual C++ 5.0 and later, bool is implemented as a built-in type with a size of 1 byte.

That type's class-like semantics are apparently not fully suppressed. Even

bool b;
b.operator std::string();

compiles (giving a seemingly empty string), implying that the internal class has a conversion operator template.

like image 141
Columbo Avatar answered Oct 23 '22 15:10

Columbo