gpt4 book ai didi

c++ - 在模板参数中,哪些规则允许编译器推断数组的项数?

转载 作者:行者123 更新时间:2023-12-05 08:37:25 27 4
gpt4 key购买 nike

给定以下两个程序——除了模板函数 len() 的定义外完全相同:

// ================================
// a.cc
// ================================
#include <iostream>

template<class T, std::size_t n>
std::size_t len(T (&v)[n]) { return n; }

int main()
{
int arr[] = { 1,2,3 };

std::cout << len(arr) << std::endl;
}
// ================================
// b.cc
// ================================
#include <iostream>

template<class T, std::size_t n>
std::size_t len(T v[n]) { return n; }

int main()
{
int arr[] = { 1,2,3 };

std::cout << len(arr) << std::endl;
}

使用 g++ 时,第一个程序按预期编译和运行。但是第二个不编译。这是诊断:

b.cc: In function ‘int main()’:
b.cc:13:25: error: no matching function for call to ‘len(int [3])’
std::cout << len(arr) << std::endl;
^
b.cc:7:13: note: candidate: template<class T, long unsigned int n> std::size_t len(T*)
std::size_t len(T v[n]) { return n; }
^
b.cc:7:13: note: template argument deduction/substitution failed:
b.cc:13:25: note: couldn't deduce template parameter ‘n’
std::cout << len(arr) << std::endl;

为什么编译器能够在第一种情况下推断出数组中的项目数,而在第二种情况下却不能?在 C++11 或 C++17 标准中,是什么导致必须编写 T (&v)[n] 而不是 T v[n]

最佳答案

[temp.deduct] 涵盖了模板参数推导[强调我的]:

/1 When a function template specialization is referenced, all of thetemplate arguments shall have values. The values can be explicitlyspecified or, in some cases, be deduced from the use or obtainedfrom default template-arguments.

/2 (... regarding explicit template argument list: not relevant here)

/3 After this substitution is performed, the function parameter typeadjustments described in [dcl.fct] are performed. [ Example: Aparameter type of “void (const int, int[5])” becomes“void()(int,int)”. — end example ] [...]

注意对[dcl.fct]的引用和/3中的相关(非规范)示例,显示了对值类型数组函数参数的调整int[N]int* ,表示非类型模板参数 N不能从传递给值类型数组参数的参数中推断出来(N 在此上下文中无用/被忽略)。

函数调用的模板参数推导,特别是在 [temp.deduct.call] 中;区分您的两个示例的相关部分是 [temp.deduct.call]/2.1 ,它表示如果调用的参数(表示为 A )是数组类型,并且参数类型(表示为 P )不是引用类型,则指针类型用于类型推导:

/2 If P is not a reference type:

  • (2.1) If A is an array type, the pointer type produced by the array-to-pointer standard conversion is used in place of A for typededuction; otherwise, [...]

而当P 引用类型,如下例所示:

template<class T, std::size_t n>
std::size_t len(T (&v)[n]) { return n; }

[temp.deduct.call]/2.1 不适用,并且对于以下对名为 len 的函数的调用以数组作为参数

int arr[] = { 1,2,3 };
(void)len(arr);

名称查找会找到函数模板len , 模板参数推导随后将应用于 P作为T[N] (根据 [temp.deduct.call]/3 )和 A作为int[3]对于len的单一功能参数, 推导出 TintN3对于参数类型的完整类型推导 P ;根据 [temp.deduct.type]/1 :

Template arguments can be deduced in several different contexts, butin each case a type that is specified in terms of template parameters(call it P) is compared with an actual type (call it A), and anattempt is made to find template argument values (a type for a typeparameter, a value for a non-type parameter, or a template for atemplate parameter) that will make P, after substitution of thededuced values (call it the deduced A), compatible with A.

即非类型模板参数N是单个函数参数的 type 的一部分(类型模板参数 T 也是如此)。

关于c++ - 在模板参数中,哪些规则允许编译器推断数组的项数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65619713/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com