Как правильно определить ARRAYSIZE?
От: Аноним  
Дата: 14.02.05 16:13
Оценка:
Самый простой вариант:
#define ARRAYSIZE(ar) (sizeof(ar)/sizeof(ar[0]))

Этот вариант применим только к массивам объявленным статически:
TCAHR ar[56];

Как заставить компилятор генерировать ошибку если в качестве параметра передается указатель?
Re: Как правильно определить ARRAYSIZE?
От: Bell Россия  
Дата: 14.02.05 16:22
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Самый простой вариант:

А>#define ARRAYSIZE(ar) (sizeof(ar)/sizeof(ar[0]))

А>Этот вариант применим только к массивам объявленным статически:

А>TCAHR ar[56];

А>Как заставить компилятор генерировать ошибку если в качестве параметра передается указатель?


Например так:

template <class T, int N>
int arr_sz(T (&arr)[N])
{
   return N;
}

int main()
{
   int arr[10];
   int sz = arr_sz(arr);//Ok

   int* p = 0;
   sz = arr_sz(p);//error: no instance of function template "arr_sz" matches the argument list

   return 0;
}
Любите книгу — источник знаний (с) М.Горький
Re: Как правильно определить ARRAYSIZE?
От: Павел Кузнецов  
Дата: 14.02.05 16:26
Оценка:
> #define ARRAYSIZE(ar) (sizeof(ar)/sizeof(ar[0]))

> Этот вариант применим только к массивам объявленным статически:

> TCAHR ar[56];

> Как заставить компилятор генерировать ошибку если в качестве параметра передается указатель?


Если не требуется, чтобы результатом было integral constant expression, можно написать шаблон функции:
template<class T, int n>
std::size_t array_size(T (&array)[n])
{
   return n;
}
Posted via RSDN NNTP Server 1.9
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re: Как правильно определить ARRAYSIZE?
От: korzhik Россия  
Дата: 14.02.05 19:33
Оценка: 87 (11) :)
Здравствуйте, Аноним, Вы писали:

А>Самый простой вариант:

А>#define ARRAYSIZE(ar) (sizeof(ar)/sizeof(ar[0]))

А>Этот вариант применим только к массивам объявленным статически:

А>TCAHR ar[56];

А>Как заставить компилятор генерировать ошибку если в качестве параметра передается указатель?


Если требуется compile-time integral constant, то можно так

template<class T, std::size_t N> 
char(&lenghtOf(T(&)[N]))[N];

#define lenghtOf(arr) sizeof(lenghtOf(arr))
Re[2]: Как правильно определить ARRAYSIZE?
От: Tonal- Россия www.promsoft.ru
Дата: 15.02.05 16:30
Оценка:
K>Если требуется compile-time integral constant, то можно так
K>
K>template<class T, std::size_t N> 
K>char(&lenghtOf(T(&)[N]))[N];

K>#define lenghtOf(arr) sizeof(lenghtOf(arr))
K>

Здорово!
РАботает даже на borlande!
... << RSDN@Home 1.1.4 beta 4 rev. 309>>
Re[2]: Как правильно определить ARRAYSIZE?
От: Аноним  
Дата: 15.02.05 17:11
Оценка:
Здравствуйте, korzhik, Вы писали:

K>Здравствуйте, Аноним, Вы писали:


А>>Самый простой вариант:

А>>#define ARRAYSIZE(ar) (sizeof(ar)/sizeof(ar[0]))

А>>Этот вариант применим только к массивам объявленным статически:

А>>TCAHR ar[56];

А>>Как заставить компилятор генерировать ошибку если в качестве параметра передается указатель?


K>Если требуется compile-time integral constant, то можно так


K>
K>template<class T, std::size_t N> 
K>char(&lenghtOf(T(&)[N]))[N];

K>#define lenghtOf(arr) sizeof(lenghtOf(arr))
K>


упппс, где такие фокусы описываются, где про это можно почитать?
эт что-то из метапрограммирования, э?
Re[3]: Как правильно определить ARRAYSIZE?
От: korzhik Россия  
Дата: 15.02.05 17:47
Оценка: 26 (5)
Здравствуйте, Аноним, Вы писали:

K>>template<class T, std::size_t N> 
K>>char(&lenghtOf(T(&)[N]))[N];

K>>#define lenghtOf(arr) sizeof(lenghtOf(arr))


А>упппс, где такие фокусы описываются, где про это можно почитать?

А>эт что-то из метапрограммирования, э?

читать про это в учебнике по C++
если надо могу объяснить что значит такая запись...
Итак:
template<class T, std::size_t N> 
char(&lenghtOf(T(&)[N]))[N];


T(&)[N] — это есть ссылка на массив, имя ссылки мы здесь убрали потому что оно нам не надо.
  char A[10];
  char(&arr_ref)[10] = A; // скобки здесь необходимы, 
  // потому что если их убрать, то получится массив ссылок, который не допустим

  char& ref_arr[10]; // error


далее, чтобы было понятнее, зададимся задачей написать функцию которая принимает ссылку на массим char'ов из 10 элементов
и её же возвращает.
Попробуем реализовать:
char(&)[10] ref2ref(char(&ref)[10])
{
  return ref;
}

Упс, вылезла ошибка!
Попробуем по другому:
char (& ref2ref(char(&ref)[10]) )[10]
{
  return ref;
}

Вот так всё нормально! Вот такой синтаксис.

Теперь посмотрим на нашу дурацкую, непонятную запись ещё раз:
template<class T, std::size_t N> 
char(&lenghtOf(T(&)[N]))[N];

теперь мы можем сказать что это!
Это — объявление шаблонной функции lenghtOf, которая принимает ссылку на массив элементов типа T размером N и возвращает ссылку на массив char'ов размером N. Так как это шаблонная функция то компилятор сделает вывод аргументов.
То есть если мы напишем
  int A[10];
  lenghtOf(A);

то компилятор сам додумается что вместо T надо подставить int, а вместо N подставить 10.
Также нам не надо определять тело функции, достаточно только нашего объявления, так как оператор sizeof интерисует только возвращаемый тип нашей функции, саму функцию он не вызывает.
Теперь осталось написать только макрос, для удобства:
#define lenghtOf(arr) sizeof(lenghtOf(arr))

ну здесь всё просто.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.