At least by my reading of N3337, gcc is correct and MSVC is incorrect (unless you disable its extensions).
The path starts at §4 of the standard:
Standard conversions are implicit conversions with built-in meaning. Clause 4 enumerates the full set of such conversions.
So, the only standard conversions that exist are those listed in clause 4. Not every possible standard conversion can be applied in every situation though. Only those that fit together into a standard conversion sequence can be used. A standard conversion sequence is specified as follows:
— Zero or one conversion from the following set: lvalue-to-rvalue conversion, array-to-pointer conversion, and function-to-pointer conversion.
— Zero or one conversion from the following set: integral promotions, floating point promotion, integral conversions, floating point conversions, floating-integral conversions, pointer conversions, pointer to member conversions, and boolean conversions.
— Zero or one qualification conversion.
Here we're starting from a pointer to a function, so the conversions under the first bullet point can't apply. We don't need/care about a qualification conversion, so we don't care about the third bullet point either.
To convert from pointer to function
to pointer to void
would clearly be a pointer conversion. These come in exactly three varieties. At §4.10/1 we have pointer conversions starting from null pointer constants (which clearly doesn't apply here). §4.10/2 covers conversions starting from:
A prvalue of type "pointer to cv T" where T is an object type [...]
That clearly doesn't apply here either, because a function isn't an object. The third option is:
A prvalue of type “pointer to cv D”, where D is a class type [...]
Again, a function isn't a class type, so that can't apply either.
That leaves us with only one option: a single conversion directly from "pointer to function" to "Boolean". That, of course, is a Boolean conversions. §4.12 says:
A prvalue of arithmetic, unscoped enumeration, pointer, or pointer to member type can be converted to a prvalue of type bool.
So, our value can be converted to a Boolean if and only if 1) it's a prvalue, and 2) it's a pointer. That probably seems pretty obvious, but if we want to confirm, we can look to the definition of the address-of operator at §5.3.1/2 and 5.3.1/3:
The result of each of the following unary operators is a prvalue.
That fulfills the first requirement.
The result of the unary & operator is a pointer to its operand. The operand shall be an lvalue or a qualified-id. If the operand is a qualified-id naming a non-static member m of some class C with type T, the result has type “pointer to member of class C of type T” and is a prvalue designating C::m. Otherwise, if the type of the expression is T, the result has type “pointer to T” and is a prvalue that is the address of the designated object (1.7) or a pointer to the designated function. [emphasis added]
That clearly fulfills the second requirement--the result is a pointer.
Since those requirements have been met, the conversion can/will happen. The result of the conversion is as follows (back to §4.12):
A zero value, null pointer value, or null member pointer value is converted to false;
any other value is converted to true.
Since we started with a pointer to an actual function, we can't have a null pointer. That leaves only one possibility: "any other value is converted to true."
Precisely as the warning from gcc said, the only possible result of the conversion is a Boolean with the value true
. That will print out as "1" by default, or "true" if boolalpha
has been set to true.