为什么类型推导不能按预期工作
why type deduction does not work as expected?
我有一个关于C++元编程中的类型推导的小问题。有一定的功能做一些动作。
main.cpp
template<typename T> void foo(T arg) {
// do some action on argument
std::cout << typeid(arg).name() << std::endl;
}
int main(int argc, char** argv) {
int array[100] = {0};
std::cout << typeid(array).name() << std::endl;
foo(array);
return 0;
}
输出:
A100_i
Pi
为什么函数foo((中的arg与函数main((中数组有另一种数据类型?
实际上,当您将数组传递给函数时,它会衰减为指针类型。因此推导出T
是int*
,而不是int[100]
。
如果要防止衰减,请通过引用接受参数。:
template<typename T> void foo(T & arg) //Note `&` here!
{
// do some action on argument
std::cout << (typeid(arg).name() << std::endl;
}
现在它将打印您期望的内容,即A100_i
。请参阅此在线演示。
问题:当我们按值传递时,为什么数组会衰减为指针类型
答:因为在C++中,数组(和函数(不能通过值传递。语言不允许这样。相反,当它们作为函数参数传递时,该语言要求它们衰减为指针类型。为了防止衰变,我们需要将它们作为引用传递。
因为C风格的数组已损坏。特别是,你不能具有一个C风格数组类型的函数参数;如果你写一个函数(暂时忘记模板(:
void foo( int arg[100] );
该语言要求编译器将其视为:
void foo( int* arg );
(而100
只是一个注释—它被编译器(。
为了在模板的情况下支持这一点,如果编译器正在尝试匹配非引用模板参数,它将把数组参数转换为指针,并键入推导将产生指针类型,而不是数组类型。
结果是,您永远不应该编写函数(模板或以其他方式(期望C样式数组(除了第二个main
的自变量,在这里您别无选择(。
由于这种破碎只存在于C兼容性,当引用卷入的因此:
template < typename T, size_t N >
void foo( T (&arg)[ N ] );
会起作用,并且在两种情况下都会给您相同的结果。如果您认为您的函数可能同时调用C风格的数组和其他东西(例如std::vector(,您可以两者都超载。上面的版本更专业,并且如果可能的话将优选于更通用的版本。
更好的解决方案是完全避免使用C型数组,但是它们对于初始化的静态变量很有用;它是只有使用C风格的数组,才能让编译器计数元素的数量,并定义数组的大小根据初始值设定项列表。并具有静态初始化;std::vector
将在运行时,但用作静态变量,可能会导致初始化问题。C型数组和
- C++从其他 constexpr 创建 lambda 不能按顺序执行 Constexpr
- std::chrono::d uration 可以按秒初始化,但不能按毫秒初始化?
- 为什么"std::is_function_v"不能按预期工作?
- 我怎么不能按课程代码的降序对数字进行排序
- 我的代码是完整的,至少我相信它是...为什么它不能按预期运行?
- 为什么将可执行文件重命名为临时文件的此代码段不能按预期工作?
- 为什么我不能按预期初始化长篇
- c++类函数在另一个函数中不能按预期工作
- 为什么我不能按值将右值 std::stringstream 传递给函数?
- 为什么这个简单的批处理方法不能按预期工作?
- 为什么 std::is_copy_constructible 不能按预期工作
- 为什么 std::codecvt<wchar_t、char、mbstate_t> 不能按定义工作?
- 为什么不能按名称打印成员函数的地址?
- 为什么我的内联汇编程序不能按预期工作
- 这个模板"specialization"代码在做什么,为什么它可以编译但不能按预期工作?
- 创建了我自己的向量类.可以重载流运算符,但不能按值c++打印
- 如果函数参数类型是ABC,为什么不能按值传递?
- 为什么类型推导不能按预期工作
- 为什么"extern const int n;"不能按预期工作?
- 在c++中对整数数组进行线性搜索时,SSE比较不能按预期工作