C++ 模板非类型参数

C++ 模板非类型参数,c++,templates,c++11,arguments,linkage,C++,Templates,C++11,Arguments,Linkage,$14.3.2-“…非类型、非模板参数的模板参数应为以下参数之一: …一个常量表达式(5.19),用于指定具有静态存储持续时间和外部或内部链接的对象的地址,或具有外部或内部链接的函数…” 在下面显示的代码中,我无法理解为什么不允许“name2”和“name3”作为非类型模板参数。我在Windows上使用GCC4.7.2 “name2”和“name3”都是数组的名称,因此都是常量表达式。此外,“name2”具有内部链接,“name3”具有静态链接和内部链接 template<char con

$14.3.2-“…非类型、非模板参数的模板参数应为以下参数之一:

…一个常量表达式(5.19),用于指定具有静态存储持续时间和外部或内部链接的对象的地址,或具有外部或内部链接的函数…”

在下面显示的代码中,我无法理解为什么不允许“name2”和“name3”作为非类型模板参数。我在Windows上使用GCC4.7.2

“name2”和“name3”都是数组的名称,因此都是常量表达式。此外,“name2”具有内部链接,“name3”具有静态链接和内部链接

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>();
}
template void f()
{
}
字符名称1[]=“Hi”;
静态字符名称2[]=“Hi”;
常量静态字符名称3[]=“Hi”;
char*name4=“嗨”;
int main()
{
f();
f();
f();
f();
}

正如@Nawaz正确猜测的那样,这是一个实现错误,而不是标准中的一个神秘角落


具体来说,gcc似乎有问题。除了与标准相反的最后一个
name4
,其余的都可以用编译,我认为问题在于您使用的表达式实际上不是指针而是数组,指针衰减只适用于
name1
。正如@KonradRudolph在评论中指出的那样,这很可能是一个编译器错误,C++11标准的第14.3.2节允许它,而
name1
name2
name3
之间没有本质上的区别

作为一种变通方法,以下内容将使用GCC 4.7.2使用
-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>();
}
template void f()
{
}
字符名称1[]=“Hi”;
静态字符名称2[]=“Hi”;
常量静态字符名称3[]=“Hi”;
int main()
{
f();
f();
f();
}

在C++98模式下,它不会编译,因为强制转换的结果从来不是一个常量表达式,而在C++11模式下,它可能是一个常量表达式。

它是否
char*name4=“Hi”
compile?@Nawaz-yes
错误:“name4”不是有效的模板参数,因为“name4”是变量,而不是变量的地址。
@Nawaz:No。name4不是常量表达式,而是变量名。@Chubsdad:yes。我在想。它不应该编译@纳瓦兹:是的,如果没有
name4
it,为什么自动指针衰减不能在这里工作?我怀疑编译器的错误是相反的。数组当然具有正确的链接,并且是常量表达式;“我看不出有什么理由它们不起作用。@KonradRudolph:你很可能是对的!我在标准中找不到任何关于常数表达式中使用的自动衰减的引用。可能它是隐式指定的elsewere,但我认为常量表达式要求有点。。。让我们说“稠密”。@KonradRudolph:对,它甚至给出了一个类似于这个例子的例子。答案更新了。我猜是这样。但现在我很好奇为什么不允许使用字符串文字。在C++03中,它们是不允许的,因为它们具有内部链接(在C++11中也是如此)。因此,字符串文字似乎满足本文第三个项目符号的所有条件section@Chubsdad:不允许使用字符串文字,可能是因为每次使用相同值的字符串文字时,它们不一定是相同的字符串,即它们可能具有不同的地址。意思是,
bool b=(“hello”==“hello”)
可能会给你
false
@康拉德·鲁道夫:不,他们是不允许的。参见§14.3.2/1(n3483)。@Nawaz是的,当然。在聊天中责备R.Martinho,他误会了我+天哪!我没有注意到您可以在liveworkspace:D上选择Clang3.2