内置数组的大小是什么类型?
What is the type of a built-in array's size?
在推导非类型模板形参时,例如n
, n
的类型必须在形参和实参之间完全匹配。因此,以下代码将无法编译(至少在GCC和clang上):
#include <array>
template <int n> void f(std::array<int, n> const&) {}
int main() {
std::array<int, 3> arr;
f(arr);
}
这是因为std::array
声明为
template <typename T, std::size_t n> class array;
而不是
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]);
...
那么,说真的,内置数组的大小类型是重载的?
从§8.3.4 [dcl.array]/1:
如果常量表达式(5.19)则它必须是std::size_t类型的转换后的常量表达式,且其值必须大于零。常量表达式指定数组
的范围(元素个数)。
类型为std::size_t
。
其他类型通常工作的原因是,根据§14.3.2 [temp.arg.nontype]/5:
,转换是在传入的类型上完成的。对于整型或枚举型的非类型模板形参,应用已转换常量表达式(5.19)中允许的转换。
出自§5.19 [expr.const]/3:
整型常量表达式是整型或无作用域枚举类型的表达式,隐式转换为右值,其中转换后的表达式是核心常量表达式。
snipp (提到这些可以用作数组边界)
转换后的T类型常量表达式是隐式转换为T类型右值的表达式,其中转换后的表达式是核心常量表达式,隐式转换序列只包含用户定义转换、左值到右值转换(4.1)、整型提升(4.5)和整型转换(4.7),而不包含窄化转换(8.5.4)。
最后,§4.7 [convr .integral]/3:
如果目的类型是有符号的,如果该值可以用目的类型(和位域宽度)表示,则该值不变;否则,该值为实现定义。
如果绑定值符合参数类型,则转换成功。否则,您将以实现定义的绑定值结束。
数组是一种特殊情况,正如ectamur的回答所指出的:
§14.8.2.5 [temp.deduct.type]/17:
如果在具有非类型模板形参的函数模板声明中,非类型模板形参在函数形参列表的表达式中使用,并且如果推导出相应的模板实参,则模板实参的类型必须与模板形参的类型完全匹配,但从数组绑定中推导出的模板实参可以是任意整型。
这在14.8.2.5 [temp.deduct.type]第17段中有涉及:
17 -[…]模板实参的类型必须与模板形参的类型完全匹配,但从数组中导出的模板实参可以是任意整型。
在http://wg21.cmeerw.net/cwg/issue1770中,它被改进为更通用的:
17 -如果
P
有包含<i>
的形式,且A
对应值的类型与i
不同,则推导失败。如果P
的形式包含[i]
,并且i
的类型不是整型,则推导失败。
因此,数组边界可以推导为任何整型,但非类型模板形参必须推导为模板定义中的实际类型。
实际上,c++ 11版本的标准中没有任何地方指定数组边界的首选类型;数组边界(在[dcl.array]中)指定为"一个整型常量表达式,其值必须大于零"。在c++ 14的最新草案中,这被修改为"类型为std::size_t
[…]的转换常量表达式(5.19)";修改后的定义可以追溯到n3306。有点奇怪的是,这种变化被描述为"相应的调整[…]]为了一致性",暗示编辑认为size_t
是正确的类型是不言而喻的。
C数组的大小是编译时常量,由编译器管理(运行时没有关于C数组大小的信息),当你实例化模板时,编译器只检查实际大小是否适合提供的模板类型。例子:
template <typename T, char n > void f(T (&)[n]) {}
int main() {
int a[1000];
f(a);
}
即使int a[20];
成功,这个也会失败。
- 静态自动 constexpr t = { "red" , "black" , "green" } 是什么类型;派生到?
- 这是什么类型的C++语法,我应该采取什么步骤来理解这一点
- 这在C++是什么类型的错误?
- int(int)& 或 int(int) const &是什么类型?
- 我如何找出3D容器的元素是什么类型
- 在 c 和 c++ 中,二维数组的元素是什么类型?
- 这个 lambda 的参数是什么类型?
- 转换逻辑目标是什么类型
- 如果我创建一个修改值的迭代器,静态成员"reference"应该是什么类型?
- 这是什么类型的行为
- 给定以下内容,"function"是什么类型?
- C++:文本文件中的数据是什么类型的
- C++11 中的"auto var = {condition} ? 1 : 1.0"是什么类型?是双精度还是整数?
- C++中的 decltype(this) 是什么类型
- 如何知道模板<类型名称类型>是什么类型?
- 内置数组的大小是什么类型?
- c++ 11中的std::chrono::high_resolution_clock::now()是什么类型?
- 在Microsoft Visual C++中,光线跟踪器应该是什么类型的项目
- 如何为delete编写一个C包装器,既快速又释放给定的任何类型,而不告诉它是什么类型
- 如何编写一个函数,无论数组是什么类型都输出它