Firstly, In your both code sections, the evaluation context all require the postfix-expression to be a constant expression. The definition of function template foo
satisfies the requirements of a constexpr function
due to its parameter is of literal type.
id-expression a
and x
are all glvalue which evaluation determine the identity of an object, but the only difference is that, In your fist code. copy-initialize the parameter from a
only require identity conversion, because of the following rules:
When a parameter of reference type binds directly to an argument expression, the implicit conversion sequence is the identity conversion, unless the argument expression has a type that is a derived class of the parameter type, in which case the implicit conversion sequence is a derived-to-base Conversion
And it does nothing, due to
[over.ics.scs#2]
As described in Clause [conv], a standard conversion sequence is either the Identity conversion by itself (that is, no conversion)
And the remain expressions are all constant expressions. So, for foo(a)
this expression, it's a constant expression.
For foo(x)
, because x
is an id-expression of reference type that subject to this rule:
an id-expression that refers to a variable or data member of reference type unless the reference has a preceding initialization and either
- it is initialized with a constant expression or
- its lifetime began within the evaluation of e;
The lifetime of x
began before the evaluation of foo(x)
and it isn't initialized with a constant expression because std::string a;
is not a glvalue constant expression. If you modify the std::string a;
to static std::string a;
,then it will be ok.