C ++ countof Реализация для массивов-членов - PullRequest
3 голосов
/ 06 ноября 2019

Я пытаюсь создать эквивалент макроса Visual Studio _countof, используя шаблоны C ++. Ниже приведены мои предлагаемые определения:

template<typename T, size_t N>
inline constexpr size_t countof(T const (&array)[N]) {
    return N;
}
template<typename T, typename U, size_t N>
inline constexpr size_t countof(T const (U::&array)[N]) {
    return N;
}

Второе объявление выше было попыткой исправить следующий код, который генерирует ошибку времени компиляции в g ++ 9 с сообщением: «error: недопустимое использование non-static элемент данных 'foo :: bar' ":

struct foo {
    int const bar[4];
    static_assert(countof(bar) == 4);
};

Однако, когда я добавляю второе определение и изменяю утверждение на использование foo::bar, g ++ генерирует ошибку:« error: »templateconstexpr const size_t countof 'конфликтует с предыдущим объявлением ".

Я могу изменить код для использования указателя на член (вместо ссылки на член), но, похоже, в этом нет необходимости. Кто-нибудь знает способ создания версии countof, которая компилируется только при передаче массива и разумно работает как для свободных, так и для массивов переменных-членов?

Ответы [ 2 ]

2 голосов
/ 06 ноября 2019

Проблема в том, что использование bar недопустимо в static_assert(countof(bar) == 4);, вам нужен экземпляр foo и получить массив bar для передачи на countof.

Я могу изменить код для использования указателя на член (вместо ссылки на член), но кажется, что в этом нет необходимости.

Вы можете изменить код для использования указателя начлен. Например,

template<typename T, typename U, size_t N>
inline constexpr size_t countof(T const (U::*array)[N]) {
    return N;
}

, затем

static_assert(countof(&foo::bar) == 4);

LIVE

Или измените countof, чтобы указать тип вместо передачи ему массива.

template<typename T>
struct count_of{};
template<typename T, size_t N>
struct count_of<T const [N]> {
    constexpr static size_t value = N;
};
template<typename T>
inline constexpr size_t countof() {
    return count_of<T>::value;
}

, затем

static_assert(countof<decltype(foo::bar)>() == 4);

LIVE

0 голосов
/ 06 ноября 2019

Я не мог найти способ сделать это без макросов, но этот пост обеспечивает способ получить как безопасность типов (гарантируя, что аргумент, передаваемый countof является массивом), так и поддержку обоих свободныхи массивы членов. Полученный код:

template<typename T, size_t N>
char (&COUNTOF_REQUIRES_ARRAY_ARGUMENT(T (&array)[N]))[N];

#define countof(x) sizeof(COUNTOF_REQUIRES_ARRAY_ARGUMENT(x))
...