Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/157.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 内置阵列的类型是什么';s码?_C++_Arrays_Templates - Fatal编程技术网

C++ 内置阵列的类型是什么';s码?

C++ 内置阵列的类型是什么';s码?,c++,arrays,templates,C++,Arrays,Templates,推导非类型模板参数时,例如n,参数和参数之间的n类型必须完全匹配。因此,以下代码将不会编译(至少在GCC和clang上): 而不是 template <typename T, int n> class array; 模板类数组; 但是,要捕获内置数组的大小,似乎任何整数类型都可以。在GCC、clang和VC++上完成以下所有工作: template <typename T, char n > void f(T (&)[n]); template <typ

推导非类型模板参数时,例如
n
,参数和参数之间的
n
类型必须完全匹配。因此,以下代码将不会编译(至少在GCC和clang上):

而不是

template <typename T, int n> class array;
模板类数组;
但是,要捕获内置数组的大小,似乎任何整数类型都可以。在GCC、clang和VC++上完成以下所有工作:

template <typename T, char n > void f(T (&)[n]);
template <typename T, short n> void f(T (&)[n]);
template <typename T, int   n> void f(T (&)[n]);
...
模板空f(T(&)[n]);
模板空隙f(T(&)[n]);
模板空隙f(T(&)[n]);
...

因此,说真的,内置数组的大小类型过载了?

C数组的大小是编译时常量,由编译器管理(运行时没有关于C数组大小的信息),当您实例化模板时,编译器只检查实际大小是否符合提供的模板类型。例如:

template <typename T, char n > void f(T (&)[n]) {}

int main() { 
  int a[1000];
  f(a);
}
template void f(T(&)[n]){
int main(){
INTA[1000];
f(a);
}

即使在
inta[20]时,此操作也会失败成功。

来自§8.3.4[dcl.数组]/1:

如果常数表达式(5.19) 存在时,它应为std::size_t类型的转换常量表达式,其值应大于零。常量表达式指定数组的边界(元素数)

类型为
std::size\u t

其他类型通常工作的原因是,根据§14.3.2[临时参数非类型]/5对传入的类型进行转换:

对于整型或枚举型的非类型模板参数,将应用转换后的常量表达式(5.19)中允许的转换

根据§5.19[解释常数]/3:

整型常量表达式是整型或非作用域枚举类型的表达式,隐式转换为prvalue,其中转换后的表达式是核心常量表达式

snip(提到这些可以用作数组边界)

类型T的转换常量表达式是隐式转换为类型T的prvalue的表达式,其中转换表达式是核心常量表达式,隐式转换序列仅包含用户定义的转换、左值到右值的转换(4.1)、积分提升(4.5),和积分转换(4.7),而不是缩小转换(8.5.4)

最后,§4.7[conv.integral]/3:

如果目标类型是有符号的,如果可以在目标类型(和位字段宽度)中表示,则该值不变;否则,该值由实现定义

如果绑定的值适合您的参数类型,则将成功转换它。如果没有,那么最终将得到一个为绑定定义的实现值

数组是一种特殊情况,如中所述:

§14.8.2.5[临时扣减类型]/17:

如果在具有非类型模板参数的函数模板声明中,在函数参数列表中的表达式中使用了非类型模板参数,并且如果推导了相应的模板参数,则模板参数类型应与模板参数的类型完全匹配,但是,从数组边界推导出的模板参数可以是任何整数类型


这在第14.8.2.5节[temp.Decrete.type]第17段中有说明:

17-[…][模板参数类型]应与模板参数的类型完全匹配,但从数组边界推导出的模板参数可以是任何整数类型

在这种情况下,改进为更一般的:

17-如果
p
的表单包含
,并且如果
a
的对应值的类型不同于
i
的类型,则扣减失败。如果
P
的表单包含
[i]
,并且
i
的类型不是整数类型,则扣减失败

因此,数组边界可以推导为任何整数类型,但非类型模板参数必须推导为模板定义中的实际类型


事实上,在标准的C++11版本中,没有任何地方指定数组边界的首选类型;数组边界(在[dcl.array]中)指定为“一个整型常量表达式,其值应大于零”。在最近的C++14草案中,这被修改为“类型为
std::size_t
[…]的转换常量表达式(5.19)”;更改后的定义可以追溯到。有点奇怪的是,这一变化被描述为“为了一致性而进行的相应调整[…],这意味着编辑们认为显然
size\u t
是正确的类型。

记住这是
std::size\u t
中的
std::size\u t
。你的帖子没有回答这个问题。OP不是问容器使用什么大小的类型,而是问为什么在问题中的上下文中可以使用
size\t
以外的类型。换句话说,非类型模板参数推导中不允许进行窄化转换。错误消息是什么?隐式积分转换并不是什么新鲜事…@Lightness Races in Orbit:而这对于非类型模板参数的类型来说是新的东西。
14.8.2.5
激发一切:-)内置数组与以往一样特殊在C++中。考虑<代码>返回的类型> <代码>操作符,我觉得它有点明显:
template <typename T, char n > void f(T (&)[n]);
template <typename T, short n> void f(T (&)[n]);
template <typename T, int   n> void f(T (&)[n]);
...
template <typename T, char n > void f(T (&)[n]) {}

int main() { 
  int a[1000];
  f(a);
}