Domanda

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?

È stato utile?

Soluzione

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.

Altri suggerimenti

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.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top