Does lvalue-to-rvalue conversion is applied to non-type lvalue template argument?

Viewed 43
struct S{
   constexpr S() {};
};
template <auto x> void f();

int main() {

    S s{};
    f<s>();
}

First off, per [temp.arg.nontype]/1

If the type T of a template-parameter (13.2) contains a placeholder type (9.2.9.6) or a placeholder for a deduced class type (9.2.9.7), the type of the parameter is the type deduced for the variable x in the invented declaration

T x = template-argument;

If a deduced parameter type is not permitted for a template-parameter declaration (13.2), the program is ill-formed.

Our template parameter contains a placeholder type auto, so the type of the parameter is the type deduced for the variable x in the invented declaration auto x = s; In this case, the type of the parameter is S, and S is a permitted type for the parameter declaration because S is a structural literal type.

Second, per [temp.arg.nontype]/2

A template-argument for a non-type template-parameter shall be a converted constant expression (7.7) of the type of the template-parameter.

This means the template-argument s shall be a converted constant expression. So per [expr.const]/10:

A converted constant expression of type T is an expression, implicitly converted to type T, where the converted expression is a constant expression and the implicit conversion sequence contains only

  • [..]
  • (10.2) — lvalue-to-rvalue conversions (7.3.2)
  • [..]

I'm not sure whether or not the lvalue s is converted to prvalue before any implicit conversions are applied to it. Note the definition of converted constant expression in C++14 is relatively changed. N4140 §5.19 [expr.const]/3: (emphasis mine)

A converted constant expression of type T is an expression, implicitly converted to a prvalue of type T, where the converted expression is a core constant expression and the implicit conversion sequence contains only [..]

So per C++14, It's guaranteed that the converted expression is converted to a prvalue before any implicit conversion is applied to it.

I'm not so sure whether or not an lvalue-to-rvalue conversion is applied to template-argument s. In other words, I'm not sure that the lvalue s is converted to a prvalue.

So in general, if I passed an lvalue as a template argument for a non-type template parameter, does an lvalue-to-rvalue conversion applied to that lvalue?

And aside from that, Is the object s constant-initialized?

0 Answers
Related