The example below attempts to use a variable of reference type as an argument for a non-type template parameter (itself of reference type). Clang, GCC and VC++ all reject it. But why? I can't seem to find anything in the standard that makes it illegal.
int obj = 42;
int& ref = obj;
template <int& param> class X {};
int main()
{
X<obj> x1; // OK
X<ref> x2; // error
}
CLang says:
source_file.cpp:9:7: error: non-type template argument of reference type 'int &' is not an object
Others complain in similar ways.
From the standard (all quotes from C++11; C++14 doesn't appear to have significant changes in relevant parts):
14.3.2/1 A template-argument for a non-type, non-template template-parameter shall be one of:
...
- a constant expression (5.19) that designates the address of an object with static storage duration and external or internal linkage ... expressed (ignoring parentheses) as
&
id-expression, except that the&
... shall be omitted if the corresponding template-parameter is a reference...
Now what's a constant expression:
5.19/2 A conditional-expression is a core constant expression unless it involves one of the following as a potentially evaluated subexpression (3.2)...
...
- an id-expression that refers to a variable or data member of reference type unless the reference has a preceding initialization, initialized with a constant expression
...
As far as I can tell, ref
in X<ref>
is an id-expression that refers to a variable of reference type. This variable has a preceding initialization, initialized with the expression obj
. I believe obj
is a constant expression, and anyway if it isn't, then X<obj>
shouldn't compile either.
- So what am I missing?
- Which clause in the standard renders
X<ref>
invalid, whileX<obj>
is valid?