Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Template compilation error - standard or not?

Tags:

c++

templates

I have the following code:

template<int k>
void foo()
{
}
int main(int argc, char* argv[])
{
    int k = 1000;
    foo<k>();
    return 0;
}

which doesn't compile, but if I declare k as const, it does:

template<int k>
void foo()
{
}
int main(int argc, char* argv[])
{
    const int k = 1000;
    foo<k>();
    return 0;
}

Now, I see the logic behind why in the first case it doesn't compile and in the second it does, but is this specified by the standard?

The error I'm getting is:

Error   1   error C2971: 'foo' : template parameter 'k' : 'k' : a local variable cannot be used as a non-type argument

which isn't exactly clear, since k is a local variable also in the case it's const... right?

like image 957
Luchian Grigore Avatar asked Nov 22 '11 19:11

Luchian Grigore


2 Answers

Per the standard, 14.3.2, this must be a constant expression:

A template-argument for a non-type, non-template template-parameter shall be one of:
an integral constant-expression of integral or enumeration type; or
— the name of a non-type template-parameter; or
— the address of an object or function with external linkage, including function templates and function template-ids but excluding non-static class members, expressed as & id-expression where the & is optional if the name refers to a function or array, or if the corresponding template-parameter is a reference; or
— a pointer to member expressed as described in 5.3.1 .

GCC 4.6.2 gives a slightly more comprehensible error:

error: ‘k’ cannot appear in a constant-expression

like image 177
David Schwartz Avatar answered Nov 04 '22 19:11

David Schwartz


§14.3.2.1 says [abridged]:

A template-argument for a non-type, non-template template-parameter shall be one of:
— an integral constant-expression of integral or enumeration type;

And §5.19.1 says [abridged, emphasis mine]:

An integral constant-expression can involve only literals, enumerators, const variables or static data members of integral or enumeration types initialized with constant expressions...

Your second definition of k satisfies this, so it's allowed to be used as an ICE for the template argument.

The error is slightly misleading in that "a local variable cannot be used as a non-type argument" is true in general, but with certain restrictions it's perfectly fine.

like image 43
GManNickG Avatar answered Nov 04 '22 18:11

GManNickG