Question

I'm developing a library in C++ in order to give to developers an help to some tasks. Usually, in order to calculate the size of an array of integer (for example) in a dynamic way (without use #define SIZE or static int SIZE), I do sizeof(v) / sizeof(int). I'm trying to write a piece of code that can do for me that stuff automatically and I decided to call if lengthof. The code is here:

template <class T> int _typesize(T*) { return sizeof(T); }
#define lengthof(x) (sizeof(x) / _typesize(&x))

I use the template to get the type of the array, then I return its size in bytes. In GCC I know that it's possible to use typeof, so I can replace _typesize(&x) with sizeof(typeof(x)), but it's not possible on MSVC. _typesize is a compatible way, but I think that it can be expensive because it passes the pointer as copy. There is an elegant way to do this?

Was it helpful?

Solution

No need for macros for this task. If you have a conforming compiler

template<class T, size_t len>
constexpr size_t lengthof(T(&)[len]) {return len;}
//the parameter is an unnamed reference to a `T[len]`, 
//where `T` is deduced as the element type of the array
//and len is deduced as the length of the array.
//similar to `T(*)[len]` in C, except you can pass the array
//directly, instead of passing a pointer to it.
//added benefit that if you pass a `T*` to it, it produces a compiler error.

Or if you're using Visual Studio which is not yet conforming...

template<class T, size_t len>
std::integral_constant<size_t, len> lengthof(T(&)[len]) {return {};}
//VC++ doesn't have constexpr, so we have to use `std::integral_constant` instead :(
//but how it works is 100% identical

If you want a more portable way, macros still work best:

#define lengthof(arr) sizeof(arr) / sizeof(arr[0])
//doesn't respect namespaces, evaluates arguments multiple times
//and if you pass a `T*` to it, it evaluates to `1` depending on context.

But to reiterate my comment, I would consider all of this bad code. Use std::vector or std::array.

OTHER TIPS

Usually, you would use: sizeof(x) / sizeof(x[0]) which doesn't rely on any extensions.

The canonical C++ way to get the length of an array is sizeof(arr) / sizeof(arr[0]). Whether you want to hide that by packing it into a macro is another debate entirely.

As a side note, if your _typesize is in the global namespace then that name is reserved for the implementation and illegal to use. In a namespace it's technically legal but generally speaking you can avoid reserved name problems by just avoiding leading underscores entirely.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top