Technically, it doesn't work with any of them.
From [dcl.constexr]:
For a constexpr function or constexpr constructor that is neither defaulted nor a template, if no argument values exist such that an invocation of the function or constructor could be an evaluated subexpression of a core constant expression, or, for a constructor, a constant initializer for some object ([basic.start.static]), the program is ill-formed, no diagnostic required.
f()
and g()
are never constant expressions (neither std::cout << x
nor printf()
are constexpr functions), so the constexpr
declaration is ill-formed. But the compiler isn't required to diagnose this (in this case, it may be easy, but in the general case... not so much). What you're seeing is that your compiler was able to diagnose one problem but not the other.
But they're both wrong.