|
|
  |
Определение размера массива на этапе компиляции, Задачка |
|
|
|
Sep 11 2012, 11:57
|
Местный
  
Группа: Свой
Сообщений: 466
Регистрация: 21-06-05
Пользователь №: 6 205

|
Опять не понял Код #include <iostream>
template <typename T, int N> int len(T (& a)[N]) { return N; }
const int a[] = {1,1,1,1,2,3,4,5,6}; // 9 элементов const int b[] = {1,1,1,5,6}; // 5 элементов
volatile int d;
int foo(const int arr[]) { std::cout << "len:" << len(arr) << "\n"; }
int main() { foo(a); foo(b); } Цитата mike@mike-work:/tmp$ LC_ALL=C g++ test.cpp test.cpp: In function 'int foo(const int*)': test.cpp:15:33: error: no matching function for call to 'len(const int*&)' test.cpp:15:33: note: candidate is: test.cpp:4:5: note: template<class T, int N> int len(T (&)[N])
|
|
|
|
|
Sep 11 2012, 15:22
|

Adept
     
Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343

|
QUOTE (kurtis @ Sep 11 2012, 18:57)  Опять не понял Что тут не понятного? Вы слепили свою функцию, скормили ей массив, внутри функции массив уже не виден, а виден только указатель на него - и что, вы хотите, чтобы компилятор восстановил из указателя массив? Заведите массив внутри вашей функции и передавайте его функции len(). Массив, а не указатель. Именно тут и проявилась фича метода - невозможно по ошибке передать в функцию указатель - только массив. Такая ошибка гарантировано отлавливается на этапе компиляции.
--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
|
|
|
|
|
Sep 11 2012, 17:20
|
Местный
  
Группа: Свой
Сообщений: 466
Регистрация: 21-06-05
Пользователь №: 6 205

|
Цитата Заведите массив внутри вашей функции и передавайте его функции len(). Массив, а не указатель. Можете, пожалуйста, привести код, который решает проблему из первого сообщения?
|
|
|
|
|
Sep 11 2012, 18:30
|

фанат дивана
     
Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684

|
Цитата(kurtis @ Sep 11 2012, 23:20)  Можете, пожалуйста, привести код, который решает проблему из первого сообщения? Код #include <iostream>
template <typename T, int N> int len(T (& a)[N]) { return N; }
const int a[] = {1,1,1,1,2,3,4,5,6}; // 9 элементов const int b[] = {1,1,1,5,6}; // 5 элементов
int main() { std::cout << "len a:" << len(a) << "\n"; std::cout << "len b:" << len(b) << "\n"; }
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Sep 11 2012, 19:17
|
;
     
Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509

|
Цитата(ViKo @ Sep 11 2012, 20:03)  Такая же особенность будет в простеньком #define a_s(array) arr_sum(array, sizeof(array)/sizeof(array[0])) Это для числа элементов. А для просто размера - пойдем в обход, чтобы выловить передачу не-массива Код #define a_s(array) arr_sum(array, (sizeof(array)/sizeof(array[0])*sizeof(array[0]))  PS Задумался... в "чиста Си" от GCC уже столько костылей плюсовых... ужас - бери и делай закат Солнца.
Сообщение отредактировал _Pasha - Sep 11 2012, 19:20
|
|
|
|
|
Sep 12 2012, 01:36
|

Adept
     
Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343

|
QUOTE (ViKo @ Sep 12 2012, 00:03)  Такая же особенность будет в простеньком #define a_s(array) arr_sum(array, sizeof(array)/sizeof(array[0])) В том-то и дело, что нет.  Когда вы скормите указатель в тут шаблонную функцию, вы получите ругань компилятора. А в случае макроса код будет молча скомпилирован, но размер будет получен неверный - не длина массива, а sizeof() указателя. В этом и состоит подлость, что закрадывается ошибка, которую компилятор отловить не в силах. Шаблонная функция лишена этого недостатка. QUOTE (kurtis @ Sep 12 2012, 02:04)  Чем это принципиально отличается от sizeof и как мне внутри функции узнать размер переданого массива? (ведь в этом смысл вопроса был?) Вы разницу между f(A) и f(A, sizeof(A)/sizeof(A[0]) видите? Перечитайте, пожалуйста, самый первый пост внимательно, там подробно описано, чем не устраивает второй вариант и чего хочется добиться. Для конкретности, представьте, что задача состоит не в определении длины массива, а в подсчёте суммы его элементов, функция должна вернуть эту сумму.
--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
|
|
|
|
|
Sep 12 2012, 03:41
|
Местный
  
Группа: Свой
Сообщений: 466
Регистрация: 21-06-05
Пользователь №: 6 205

|
Медлено начинаю понимать... Код #include <iostream>
template <typename T, int N> int sum(T (& a)[N]) { int sum, i; for (i = 0, sum = 0; i < N; i++) sum += a[i];
return sum; }
const int a[] = {1,1,1,1,2,3,4,5,6}; // 9 элементов const int b[] = {1,1,1,5,6}; // 5 элементов
int main() { std::cout << sum(a) << "\n"; std::cout << sum(b) << "\n"; } Цитата mike@mike-P55A-UD4:/tmp$ for i in $(nm a.out | grep sum | cut -d" " -f 3) ; do echo $i ; c++filt $i ; done _Z3sumIKiLi5EEiRAT0__T_ int sum<int const, 5>(int const (&) [5]) _Z3sumIKiLi9EEiRAT0__T_ int sum<int const, 9>(int const (&) [9]) При выключенной оптимизации, получается 2 экземпляра функции sum(), для каждого из параметров. Конечно, это все хорошо если функции простые, и компилятор может их оптимизировать, а если нет?
|
|
|
|
|
Sep 12 2012, 03:51
|

фанат дивана
     
Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684

|
Цитата(kurtis @ Sep 12 2012, 01:04)  Чем это принципиально отличается от sizeof и как мне внутри функции узнать размер переданого массива? (ведь в этом смысл вопроса был?) Вы не совсем поняли идею. Идея именно в том, что это аналог sizeof(), но за программиста этот sizeof() автоматически подставляет компилятор. То есть, вы вместо функции Код void fome_func(int arr[], size_t arr_len) { for (int i = 0; i < arr_len; i++) foo(arr[i]); } пишете шаблон: Код template <typename T, int arr_len> void fome_func(T (& arr)[arr_len]) { for (int i = 0; i < arr_len; i++) foo(arr[i]); } Здесь исключена возможность передать размер, не соответствующий массиву - это делает компилятор. Однако при таком подходе возможно, что у вас для каждого размера массива будет сгенерирована своя функция. Если вы этого не желаете, то можно совместить подходы: Код template <typename T, int arr_len> inline void call_fome_func(T (& arr)[arr_len]) { fome_func(arr, arr_len); } Это практически полный аналог варианта с #define, но более безопасный с точки зрения контроля параметров.
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
  |
3 чел. читают эту тему (гостей: 3, скрытых пользователей: 0)
Пользователей: 0
|
|
|