[英]What does the standard say about char arrays as template arguments?
During my research for an answer for this question I found (I did not know that before) that gcc and clang allow char
arrays to be template arguments if they are declared static
.在我研究这个问题的答案时,我发现(我之前不知道)gcc 和 clang 允许
char
数组作为模板参数,如果它们被声明为static
。 Eg this code compiles with gcc and clang:例如,这段代码用 gcc 和 clang 编译:
#include <type_traits>
template <int N, const char (&string)[N]>
auto foo()
{
if constexpr (string[0] == 'i')
return 0;
else
return 3.14f;
}
void bar()
{
static constexpr char string1[] = "int";
static constexpr char string2[] = "float";
auto i = foo<sizeof(string1), string1>();
auto f = foo<sizeof(string2), string2>();
static_assert(std::is_same_v<decltype(i), int>);
static_assert(std::is_same_v<decltype(f), float>);
}
MSVC also allows that. MSVC 也允许这样做。 However, to make it work with MSVC, I have to declare the two strings in the global namespace.
但是,要使其与 MSVC 一起使用,我必须在全局命名空间中声明这两个字符串。 Then it works just as well.
然后它也能正常工作。
So my question is: What does the standard say about this?所以我的问题是:标准对此有何看法? Which compiler (if any) is right?
哪个编译器(如果有)是正确的?
This issue has been fixed in VS 2019 version 16.4 (msvc v19.24): https://developercommunity.visualstudio.com/content/problem/341639/very-fragile-ice.html此问题已在 VS 2019 版本 16.4 (msvc v19.24) 中修复: https : //developercommunity.visualstudio.com/content/problem/341639/very-fragile-ice.html
This is a change from C++14 to C++17 that looks like MSVS hasn't caught up with.这是从 C++14 到 C++17 的变化,看起来 MSVS 没有赶上。 Previously in [temp.arg.nontype] a non type argument had to be
以前在[temp.arg.nontype] 中,非类型参数必须是
A template-argument for a non-type, non-template template-parameter shall be one of:
非类型、非模板模板参数的模板参数应为以下之一:
for a non-type template-parameter of integral or enumeration type, a converted constant expression ([expr.const]) of the type of the template-parameter;
对于整数或枚举类型的非类型模板参数,模板参数类型的转换常量表达式([expr.const]); or
或者
the name of a non-type template-parameter;
非类型模板参数的名称; or
或者
a constant expression ([expr.const]) that designates the address of a complete object with static storage duration and external or internal linkage or a function with external or internal linkage, including function templates and function template-ids but excluding non-static class members, expressed (ignoring parentheses) as & id-expression, where the id-expression is the name of an object or function, except that the & may be omitted if the name refers to a function or array and shall be omitted if the corresponding template-parameter is a reference;
一个常量表达式 ([expr.const]),它指定一个完整的对象的地址,具有静态存储持续时间和外部或内部链接,或者一个具有外部或内部链接的函数,包括函数模板和函数模板 ID,但不包括非静态类成员,表示(忽略括号)为 & id-expression,其中 id-expression 是对象或函数的名称,但如果名称是指函数或数组,则可以省略 &,如果对应的名称,则应省略模板参数是一个参考; or
或者
a constant expression that evaluates to a null pointer value ([conv.ptr]);
计算结果为空指针值的常量表达式 ([conv.ptr]); or
或者
a constant expression that evaluates to a null member pointer value ([conv.mem]);
计算结果为空成员指针值 ([conv.mem]) 的常量表达式; or
或者
a pointer to member expressed as described in [expr.unary.op];
一个指向成员的指针,如 [expr.unary.op] 中所述; or
或者
a constant expression of type
std::nullptr_t
.类型为
std::nullptr_t
的常量表达式。
emphasis mine强调我的
and because of bullet 3 you could not use a block scope variable as block scope variables have no linkage per [basic.link]/10并且由于第 3 条,您不能使用块作用域变量,因为块作用域变量根据[basic.link]/10没有链接
Names not covered by these rules have no linkage.
这些规则未涵盖的名称没有链接。 Moreover, except as noted, a name declared at block scope has no linkage.
此外,除非另有说明,在块范围内声明的名称没有链接。
In C++17 this changes.在 C++17 中,这发生了变化。 [temp.arg.nontype] now has
[temp.arg.nontype]现在有
A template-argument for a non-type template-parameter shall be a converted constant expression of the type of the template-parameter.
非类型模板参数的模板参数应是模板参数类型的转换常量表达式。 For a non-type template-parameter of reference or pointer type, the value of the constant expression shall not refer to (or for a pointer type, shall not be the address of):
对于引用或指针类型的非类型模板参数,常量表达式的值不得引用(或对于指针类型,不得为以下地址):
a subobject,
一个子对象,
a temporary object,
一个临时对象,
a string literal,
字符串文字,
the result of a typeid expression, or
typeid 表达式的结果,或
a predefined
预定义的 func__ variable.
func__ 变量。
This now allows you to use a block scope static variable这现在允许您使用块范围静态变量
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.