The expressions int()
and int{}
are both constant expression prvalues of integer type that evaluate to zero, and are therefore interchangeable with the literal 0
in any context that requires an integral constant expression prvalue of integer type which evaluates to zero.
Both expressions satisfy the requirements for a constant expression as specified in 5.19 Constant Expressions [expr.const].
Regarding X<int()>
, the standard specifies that int()
is not interpreted as an expression in this context:
14.3 Template arguments [temp.arg]
In a template-argument, an ambiguity between a type-id and an expression is resolved to a type-id, regardless of the form of the corresponding template-parameter.
Regarding pointer conversions:
4.10 Pointer conversions [conv.ptr]
A null pointer constant is an integral constant expression (5.19) prvalue of integer type that evaluates to zero or a prvalue of type
std::nullptr_t
.
Based on the above paragraph, both int()
and int{}
are null pointer constant expressions. This points to a (very minor) compiler bug, although there is an open Defect Report (903) which may lead to this paragraph changing:
There was a strong consensus among the CWG that only the literal 0 should be considered a null pointer constant, not any arbitrary zero-valued constant expression as is currently specified.
The following wording deals with the value of the expression int()
:
8.5 Initializers [dcl.init]
To zero-initialize an object or reference of type T means:
[omitted clauses which don't apply]
— if T is a scalar type (3.9), the object is set to the value 0 (zero), taken as an integral constant expression, converted to T
[...]
To value-initialize an object of type T means:
— if T is a (possibly cv-qualified) class type (Clause 9) with a user-provided constructor (12.1), then the default constructor for T is called (and the initialization is ill-formed if T has no accessible default constructor);
[omitted clauses which don't apply]
— otherwise, the object is zero-initialized.
An object whose initializer is an empty set of parentheses, i.e., (), shall be value-initialized.
And for the value of int{}
:
8.5.4 List-initialization [dcl.init.list]
List-initialization of an object or reference of type T is defined as follows:
— If the initializer list has no elements and T is a class type with a default constructor, the object is value-initialized.
[omitted clauses which don't apply]
— Otherwise, if the initializer list has no elements, the object is value-initialized.
All quotes from C++ Working Draft Standard N3337.