【问题标题】:How does this Array Size Template Work?这个数组大小模板是如何工作的?
【发布时间】:2011-09-16 14:06:48
【问题描述】:

我遇到了这个sn-p

template <typename T, size_t N>  
char (&ArraySizeHelper(T (&array)[N]))[N];  
#define arraysize(array) (sizeof(ArraySizeHelper(array))) 

在这篇文章中http://software.intel.com/en-us/articles/pvs-studio-vs-chromium/

我见过其他模板可以做同样的事情,比如这个

Use templates to get an array's size and end address

我理解这些,但我在这方面遇到了困难。

任何帮助将不胜感激。

【问题讨论】:

  • 您在哪些方面特别有困难?这里有许多不同的 C++ 元素在起作用。
  • 欺骗。也可以看看这个底部的解释:stackoverflow.com/questions/437150/…(这不是骗子,我现在懒得去搜索了)。
  • 链接到骗子或者它没有发生 :) 我也找不到骗子,否则我不会发布。
  • 真正的问题是为什么不使用std::extent 而不是这个丑陋的宏?

标签: c++ templates metaprogramming


【解决方案1】:

函数模板被命名为ArraySizeHelper,该函数接受一个参数,一个对T [N]的引用,并返回一个对char [N]的引用。

宏将您的对象(假设它是X obj[M])作为参数传递。编译器推断T == XN == M。所以它声明了一个返回类型为char (&amp;)[M] 的函数。然后宏用sizeof包装这个返回值,所以它真的在做sizeof(char [M]),也就是M

如果你给它一个非数组类型(例如T *),那么模板参数推断将失败。

正如@Alf 在下面指出的那样,这种混合模板-宏系统相对于替代的纯模板方法的优势在于它为您提供了一个编译时常量。

【讨论】:

  • 我只是补充一下目的,即将数组大小作为编译时间常数(它又可以用来指定原始数组的大小)。我记得是一个俄罗斯人首先提出了这种变化。不幸的是,我不记得名字了。
  • 所以,我认为该函数已声明但未定义?我很难解析语法。
  • 谢谢,我认为是返回 char (&)[M] 的语法让我大吃一惊。 C/C++ 数组语法很糟糕。
  • @Gene Bushuyev:基本上你可以在任何遵循 98 标准的编译器中使用这段代码,但你不能使用你的方法,除非编译器实现了 C++0x 特性(至少 @987654333 @ 和 extent 类型特征。
【解决方案2】:

这不是最好的方法,但既然您要问:模板函数ArraySizeHelper 的返回类型是char[N],其中函数的参数是(引用)数组大小为 N 的类型为 T。模板参数推导用匹配的数字 N 实例化这个模板,所以 sizeof(char[N]) 就是 N,这就是你得到的。

一个更好的版本可以写成如下。 (constexpr 需要 C++0x;如果省略它,这将不是常量表达式。)

template <typename T, size_t N> constexpr size_t array_size(const T (&)[N]) { return N; }

用法:

int x[20];
array_size(x); // == 20

更新:如果您在 C++0x 中,这里是另一个提供 constexpr 的解决方案,感谢 decltype:

#include <type_traits>

template <typename T> struct array_traits;
template <typename T, unsigned int N> struct array_traits<T[N]>
{
   static const unsigned int size = N;
   typedef std::decay<T>::type type;
};

// Usage:
int x[20];
array_traits<decltype(x)>::size; // == 20

【讨论】:

  • 那么出于好奇,您觉得最好的方法是什么?
  • @Jalf:更新。没有编译器宏!
  • 问题在于它不是 constexpr,不像宏。
  • @DeadMG:是的。我们能否以某种不需要宏的方式包装它?更重要的是,两者计算不同的汇编器输出吗?
  • 只需将constexpr 放在您的第一个函数模板之前,array_size(x) 在 C++0x 中也将是一个常量表达式。
【解决方案3】:

This blog on MSDN 准确地描述了它的工作原理。很有趣的故事。看看吧。

【讨论】:

    猜你喜欢
    • 2011-03-23
    • 2011-01-23
    • 1970-01-01
    • 2014-08-01
    • 2010-10-03
    • 1970-01-01
    • 2013-01-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多