Я занимаюсь разработкой библиотеки на C ++, чтобы помочь разработчикам в решении некоторых задач.
Обычно, чтобы динамически вычислить размер массива целых чисел (например) (без использования #define SIZE или static int SIZE), я делаю sizeof (v) / sizeof (int). Я пытаюсь написать кусок кода, который может сделать для меня это автоматически, и я решил позвонить, если lengthof.
Код здесь:
template <class T> int _typesize(T*) { return sizeof(T); }
#define lengthof(x) (sizeof(x) / _typesize(&x))
Я использую шаблон, чтобы получить тип массива, затем я возвращаю его размер в байтах. В GCC я знаю, что можно использовать typeof, поэтому я могу заменить _typesize (&x) с sizeof (typeof (x)), но это невозможно в MSVC. _typesize — это совместимый способ, но я думаю, что он может быть дорогим, потому что он передает указатель как копию. Есть элегантный способ сделать это?
Для этой задачи не нужны макросы. Если у вас есть соответствующий компилятор
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.
Или если вы используете Visual Studio, которая еще не соответствует …
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
Если вы хотите более переносимый способ, макросы по-прежнему работают лучше:
#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.
Но чтобы повторить мой комментарий, я бы рассмотрел весь этот плохой код. использование std::vector
или же std::array
,
Обычно вы используете: sizeof(x) / sizeof(x[0])
который не зависит от каких-либо расширений.
Канонический C ++ способ получить длину массива sizeof(arr) / sizeof(arr[0])
, Хотите ли вы скрыть это, упаковав это в макрос, — это еще одна дискуссия.
Как примечание, если ваш _typesize
находится в глобальном пространстве имен, тогда это имя зарезервировано для реализации и запрещено для использования. В пространстве имен это технически законно, но, вообще говоря, вы можете избежать проблем с зарезервированными именами, просто полностью избегая начальных подчеркиваний.