这个宏可以转换成函数吗?
在重构代码并摆脱所有那些我们现在被教导讨厌的#defines 时,我发现了这种用于计算结构中元素数量的美感:
While refactoring code and ridding myself of all those #defines that we're now taught to hate, I came across this beauty used to calculate the number of elements in a structure:
#define STRUCTSIZE(s) (sizeof(s) / sizeof(*s))
它非常有用,但它可以转换成内联函数或模板吗?
Very useful as it is but can it be converted into an inline function or template?
好的,ARRAYSIZE 会是一个更好的名字,但这是遗留代码(不知道它来自哪里,它至少有 15 年的历史)所以我按原样"粘贴它.
OK, ARRAYSIZE would be a better name but this is legacy code (no idea where it came from, it's at least 15 years old) so I pasted it 'as is'.
推荐答案
如前所述,代码实际上计算出数组中元素的数量,而不是结构.我会在需要时明确写出 sizeof() 除法??.如果我要让它成为一个函数,我想在它的定义中明确说明它需要一个数组.
As been stated, the code actually work out the number of elements in an array, not struct. I would just write out the sizeof() division explicitly when I want it. If I were to make it a function, I would want to make it clear in its definition that it's expecting an array.
template<typename T,int SIZE>
inline size_t array_size(const T (&array)[SIZE])
{
return SIZE;
}
上面类似于xtofl的,除了它防止将指针传递给它(即指向动态分配的数组)并错误地得到错误的答案.
The above is similar to xtofl's, except it guards against passing a pointer to it (that says point to a dynamically allocated array) and getting the wrong answer by mistake.
编辑:根据 JohnMcG 进行了简化.编辑:内联.
EDIT: Simplified as per JohnMcG. EDIT: inline.
不幸的是,上面没有提供编译时答案(即使编译器确实内联并优化它以使其成为引擎盖下的常量),因此不能用作编译时常量表达式.即它不能用作声明静态数组的大小.在 C++0x 下,如果将关键字 inline 替换为 constexpr(constexpr 是隐式内联的),这个问题就会消失.
Unfortunately, the above does not provide a compile time answer (even if the compiler does inline & optimize it to be a constant under the hood), so cannot be used as a compile time constant expression. i.e. It cannot be used as size to declare a static array. Under C++0x, this problem go away if one replaces the keyword inline by constexpr (constexpr is inline implicitly).
constexpr size_t array_size(const T (&array)[SIZE])
jwfearn 的解决方案适用于编译时间,但涉及在新名称的声明中有效地保存"数组大小的 typedef.然后通过该新名称初始化一个常量来计算数组大小.在这种情况下,也可以从一开始就简单地将数组大小保存为常量.
jwfearn's solution work for compile time, but involve having a typedef which effectively "saved" the array size in the declaration of a new name. The array size is then worked out by initialising a constant via that new name. In such case, one may as well simply save the array size into a constant from the start.
Martin York 的 发布的解决方案也适用于编译时间,但涉及使用非标准的 typeof() 运算符.解决这个问题的方法是等待 C++0x 并使用 decltype (到那时我们实际上不需要它来解决这个问题,因为我们将有 constexpr).另一种选择是使用 Boost.Typeof,在这种情况下我们将使用
Martin York's posted solution also work under compile time, but involve using the non-standard typeof() operator. The work around to that is either wait for C++0x and use decltype (by which time one wouldn't actually need it for this problem as we'll have constexpr). Another alternative is to use Boost.Typeof, in which case we'll end up with
#include <boost/typeof/typeof.hpp>
template<typename T>
struct ArraySize
{
private: static T x;
public: enum { size = sizeof(T)/sizeof(*x)};
};
template<typename T>
struct ArraySize<T*> {};
并通过书写使用
ArraySize<BOOST_TYPEOF(foo)>::size
其中 foo 是数组的名称.
where foo is the name of an array.
相关文章