template non type arguments

2019-04-20 07:05发布

问题:

$14.3.2 - "... 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 or a function with external or internal linkage..."

In the code shown below, I fail to understand why 'name2' and 'name3' are not allowed as non type template arguments. I am using gcc 4.7.2 on Windows.

Both 'name2' and 'name3' are names of array and hence are constant expressions. Further 'name2' is having internal linkage and 'name3' has both static and internal linkage.

template<char const *p> void f()
{

}

char name1[] = "Hi";
static char name2[]= "Hi";
const static char name3[]= "Hi";
char *name4 = "Hi";

int main()
{
    f<name1>();
    f<name2>();
    f<name3>();
    f<name4>();
}

回答1:

As @Nawaz correctly guessed, this is an implementation bug, not an esoteric corner of the standard.

Specifically, gcc seems to have trouble with it. Barring the last name4 which is against the standard, the rest of it compiles fine with clang



回答2:

I think that the problem is that the expression you use are not actually pointers but arrays, and the pointer decay only works for name1. It is most likely a compiler bug, as kindly @KonradRudolph pointed out in the comment, section 14.3.2 of the C++11 standard allows it, and there is nothing essentially different between name1, name2 and name3.

As a workaround, the following will compile with GCC 4.7.2 using -std=c++11:

template<char const *p> void f()
{
}

char name1[] = "Hi";
static char name2[]= "Hi";
const static char name3[]= "Hi";

int main()
{
    f<(char const*)&name1>();
    f<(char const*)&name2>();
    f<(char const*)&name3>();
}

In C++98 mode it does not compile because the result of a cast is never a constant expression, while in C++11 it may be.