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 declarationT 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 declarationbool t(e);
is well-formed, for some invented temporary variablet
(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.