这个函数模板如何推导出数组的大小?

发布于 2025-01-10 21:32:45 字数 424 浏览 4 评论 0原文

在以下代码中:

#include <iostream>

template <typename T, size_t N> 
void cal_size(T (&a)[N])
{ 
    std::cout << "size of array is: " << N << std::endl;
}

int main()
{
    int a[] = {1,2,3,4,5,6};
    int b[] = {1};

    cal_size(a);
    cal_size(b);
}

正如预期的那样,两个数组的大小都被打印出来。 N 如何自动初始化为数组大小的正确值(数组通过引用传递)?

In the following code:

#include <iostream>

template <typename T, size_t N> 
void cal_size(T (&a)[N])
{ 
    std::cout << "size of array is: " << N << std::endl;
}

int main()
{
    int a[] = {1,2,3,4,5,6};
    int b[] = {1};

    cal_size(a);
    cal_size(b);
}

As expected, the size of both the arrays gets printed. How does N automatically get initialized to the correct value of the array-size (arrays are being passed by reference)?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

你爱我像她 2025-01-17 21:32:45

N 不会“初始化”任何东西。它不是一个变量。它不是一个物体。 N 是一个编译时常量。 N 仅在编译期间存在。 N 的值以及实际的 T 由称为“模板参数推导”的过程确定。 TN 都是根据传递给模板函数的参数的实际类型推导出来的。

在第一次调用中,参数类型为 int[6],因此编译器推断出 T == intN == 6,生成一个单独的函数并调用它。我们将其命名为 cal_size_int_6

void cal_size_int_6(int (&a)[6]) 
{ 
  std::cout << "size of array is: " << 6 << std::endl; 
} 

请注意,此函数中不再有 TN。两者都在编译时被其实际推导值替换。

在第一次调用中,参数类型为 int[1],因此编译器推断出 T == intN == 1,生成也有一个单独的函数并调用它。我们将其命名为 cal_size_int_1

void cal_size_int_1(int (&a)[1]) 
{ 
  std::cout << "size of array is: " << 1 << std::endl; 
} 

此处相同。

您的 main 本质上可以翻译为:

int main() 
{ 
  int a[]={1,2,3,4,5,6}; 
  int b[]={1}; 

  cal_size_int_6(a); 
  cal_size_int_1(b); 
} 

换句话说,您的 cal_size 模板产生了两个不同的函数(所谓的专业化原始模板),每个都有不同的 N 值(和 T)硬编码到正文中。这就是模板在 C++ 中的工作原理。

N does not get "initialized" to anything. It is not a variable. It is not an object. N is a compile-time constant. N only exists during compilation. The value of N as well as the actual T is determined by the process called template argument deduction. Both T and N are deduced from the actual type of the argument you pass to your template function.

In the first call the argument type is int[6], so the compiler deduces that T == int and N == 6, generates a separate function for that and calls it. Let's name it cal_size_int_6

void cal_size_int_6(int (&a)[6]) 
{ 
  std::cout << "size of array is: " << 6 << std::endl; 
} 

Note that there's no T and no N in this function anymore. Both were replaced by their actual deduced values at compile time.

In the first call the argument type is int[1], so the compiler deduces that T == int and N == 1, generates a separate function for that as well and calls it. Let's name it cal_size_int_1

void cal_size_int_1(int (&a)[1]) 
{ 
  std::cout << "size of array is: " << 1 << std::endl; 
} 

Same thing here.

Your main essentially translates into

int main() 
{ 
  int a[]={1,2,3,4,5,6}; 
  int b[]={1}; 

  cal_size_int_6(a); 
  cal_size_int_1(b); 
} 

In other words, your cal_size template gives birth to two different functions (so called specializations of the original template), each with different values of N (and T) hardcoded into the body. That's how templates work in C++.

画离情绘悲伤 2025-01-17 21:32:45

它之所以有效,是因为 a 的类型是“int 的长度为 6 的数组”,而 b 的类型是“长度为 1 的数组”代码>int”。编译器知道这一点,因此它可以调用正确的函数。特别是,第一个调用调用模板实例 cal_size<6>(),第二个调用调用 cal_size<1>(),因为这些是唯一的模板实例匹配他们各自的论点。

如果您尝试调用显式模板实例,则只有尺寸正确时它才会起作用,否则参数将不匹配。考虑以下几点:

cal_size(a);    // ok, compiler figures out implicitly that N=6
cal_size<int, 6>(a); // also ok, same result as above
cal_size<int, 5>(a); // ERROR: a is not of type "array of length 5 of int"

It works because the type of a is "array of length 6 of int" and the type of b is "array of length 1 of int". The compiler knows this, so it can call the correct function. In particular, the first call calls the template instance cal_size<6>() and the second call calls cal_size<1>(), since those are the only template instantiations which match their respective arguments.

If you attempted to call an explicit template instance, it would only work if you got the size right, otherwise the arguments wouldn't match. Consider the following:

cal_size(a);    // ok, compiler figures out implicitly that N=6
cal_size<int, 6>(a); // also ok, same result as above
cal_size<int, 5>(a); // ERROR: a is not of type "array of length 5 of int"
夜巴黎 2025-01-17 21:32:45

当您声明 int a[] = {1,2,3} 时,它与 int a[3] = {1,2,3} 相同(或将重写为),因为模板化函数以以下形式接收参数T a[N],则 N 的值为 3。

when you declare int a[] = {1,2,3} it is the same as (or will be rewritten as) int a[3] = {1,2,3} since the templated function is receiving argument in form of T a[N], then N will have value of 3.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文