Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 02.09.2011, 08:56   #1
rommster
Пользователь
 
Регистрация: 05.10.2010
Сообщений: 46
По умолчанию Шаблоны, константы

Доброго времени суток. Читаю вот книжку Липпмана, наткнулся на кое-что для меня непонятное. Вот допустим такой код:

Код:
#include <iostream>

// шаблонная функция, просто печатает размер массива
template <typename Type, int size>
void print_size(Type (&r_array)[size])
{
	std::cout << size;
}

void foo(int * arr) 
{
	// error: Type (&)[] != int*
	print_size(arr);
}

int main()
{
	int a[] = { 10, 7, 14, 3, 25 };
	
	print_size(a);
	foo(a);
	
	return 0;
}
Вопрос1: что такое параметр-константа в списке параметров шаблона (int size), зачем он нужен, как он передаётся? Здесь передаётся размер массива, но как? Не догоняю... А если у меня не массив, то какой смысл в такой константе? Погуглил вот, но там в основном такой же пример с массивом...

Вопрос2: что за тип такой вообще (&)[]? Ссылка на массив? А зачем? Почему не просто массив?

Вопрос3: допустим, написал я функцию foo, ничего не делает, просто передаёт массив в ту же шаблонную ф-цию. Но тут ошибка несоответствия типов. Липман объясняет так: "вызов ошибочен, так как pval имеет тип int*, а не является l-значением типа "массив int"". А почему, когда я пишу просто
Код:
int a[] = { 10, 7, 14, 3, 25 }; print_size(a);
то всё соответствует, гм...

Туплю-туплю вот, подскажите что-нибудь) Спасибо.
rommster вне форума Ответить с цитированием
Старый 03.09.2011, 16:29   #2
onewho
Форумчанин
 
Регистрация: 29.09.2010
Сообщений: 636
По умолчанию

не хотел отвечать т.к слабо разбираюсь в шаблонах, но все молчат - поэтому опишусь:
Цитата:
что такое параметр-константа в списке параметров шаблона (int size), зачем он нужен, как он передаётся?
ну вроде как если встречается шаблонная функция то можно явно указать список шаблонных параметров. тогда компилер сгенерирует нужный вариант функции.
то есть вы имеете полное право написать
Код:
print_size<int>(a);
или
Код:
print_size<int,5>(a);
если же не указать, тогда компилятор попытается по типам переданных параметров создать нужный вариант функции.
то есть в данном случае ему удалось создать подходящий вариант, то есть подставить int (&r_array)[5]. а данные о размере массива известны еще при объявлении , ведь int a[] это неясное int a[5] в данном случае.

Цитата:
что за тип такой вообще (&)[]? Ссылка на массив? А зачем? Почему не просто массив?
да, ссылка на массив.
имхо потому что передача например T r_array[size] автоматически преобразуется к виду T* r_array, где размер неизвестен.

Цитата:
Вопрос3: допустим, написал я функцию foo, ничего не делает, просто передаёт массив в ту же шаблонную ф-цию. Но тут ошибка несоответствия типов. Липман объясняет так: "вызов ошибочен, так как pval имеет тип int*, а не является l-значением типа "массив int"". А почему, когда я пишу просто
дело в том что T r_array[size] и T* всё таки разные вещи.бытует мнение что имя массива - является указателем на его первый элемент. но это не так. имя массива может быть приведено к указателю на 1 элемент, как это и было сделано в случае с foo, и в этом плане оно потеряло свою сущность массива а стало просто адресом.

надеюсь не сказал ересь.
onewho вне форума Ответить с цитированием
Старый 03.09.2011, 17:41   #3
rommster
Пользователь
 
Регистрация: 05.10.2010
Сообщений: 46
По умолчанию

Да, спасибо, как передать константу в угловых скобках более менее понял. Только про массив как-то ещё не совсем... Это что-то типа: Type будет заменено на int, а size на 5? Т.е. из
Код:
 void print_size(Type (&r_array)[size])
будет сгенерирован экземпляр:
Код:
void print_size(int (&r_array)[5])
Ну вроде бы тоже понятно... Только вот зачем это надо? С массивом-то оно вроде удобно, чтобы не передавать размер. А какие ещё могут быть случаи? Не проще ли будет добавить параметр функции, вместо параметра шаблона, и использовать тогда более понятную запись без передачи чего-то там в угловых скобках?

Цитата:
Сообщение от onewho Посмотреть сообщение
бытует мнение что имя массива - является указателем на его первый элемент.
Ага, бытует, даже по запросу в гугле много чего подобного нашлось. Да вроде и в книжках так пишут, типа имя массива - константный указатель. А чем тогда является имя массива? По идее вещей оно же тоже адрес хранит? Плюс ещё и данные о размере массива что ли? хм...
rommster вне форума Ответить с цитированием
Старый 04.09.2011, 02:51   #4
onewho
Форумчанин
 
Регистрация: 29.09.2010
Сообщений: 636
По умолчанию

Цитата:
С массивом-то оно вроде удобно, чтобы не передавать размер.
ну в этом то и заключается данный трюк.
узнать таким образом размер массива не указывая его ясно.
Цитата:
Не проще ли будет добавить параметр функции, вместо параметра шаблона, и использовать тогда более понятную запись без передачи чего-то там в угловых скобках?
проще обычно так и делают.
Цитата:
А чем тогда является имя массива? По идее вещей оно же тоже адрес хранит? Плюс ещё и данные о размере массива что ли? хм...
имя массива - это имя массива. просто как я уже написал оно может быть преобразовано к указателю на 1ый его элемент (оно не хранит адрес, оно им по сути дела является (адресом 1 элемента)) .
вот уж данные о массиве имя массива точно не хранит, а компилятор запросто

хотя чёрт побери ... ведь если сделать sizeof(имя массива) - высветится то его реальный размер в байтах.
блин короче я сам не знаю )

призываю экспертов в тему !

Последний раз редактировалось onewho; 04.09.2011 в 02:54.
onewho вне форума Ответить с цитированием
Старый 04.09.2011, 08:41   #5
rommster
Пользователь
 
Регистрация: 05.10.2010
Сообщений: 46
По умолчанию

Цитата:
Сообщение от onewho Посмотреть сообщение
ведь если сделать sizeof(имя массива) - высветится то его реальный размер в байтах.
Погуглил малость на эту тему: sizeof() вроде как является функцией времени компиляции, поэтому странного наверное ничего и нет... Ну, так я это понял. Вот для динамического массива (указателя) она будет работать не так.

Но тогда ещё один момент, как работает оператор delete[], откуда он-то размер берёт? Значит размер как-то и для указателя хранится? В чём тогда проблема при передаче указателя в функцию, почему нельзя как-то вытащить размер?
rommster вне форума Ответить с цитированием
Старый 04.09.2011, 23:28   #6
onewho
Форумчанин
 
Регистрация: 29.09.2010
Сообщений: 636
По умолчанию

на счёт откуда delete берёт размер - в стандарте по-моему не оговорено, соответсвенно остается на поруках разработчика компилятора. подробнее сказать не могу т.к тема сложная и не совсем нужная. гуглите)

размер вытащить можно ) с помощью хитроумных операций я видел примеры на другом форуме.. щас попытался найти но что-то тему не нашёл ту ...
всё равно такие примеры абсолютно не переносимы, так что не стоит ими увлекаться, чисто для интересна почитать можно, но использовать в реальной работе - нет.
onewho вне форума Ответить с цитированием
Старый 05.09.2011, 08:16   #7
pu4koff
Старожил
 
Аватар для pu4koff
 
Регистрация: 22.05.2007
Сообщений: 9,065
По умолчанию

Шаблоны собираются на этапе компиляции, при этом будут созданы отдельные функции для всех вариантов параметров шаблонов. Отдельно для <int, 5>, отдельно для <int, 10> и <float, 18>. В случае с int*, размер массива будет доступен во время исполнения программы, т.е. компилятор не сможет заранее создать нужный экземпляр функции. Принцип С++ - максимальный объем работы выполнять во время компиляции, именно поэтому в плюсах шаблоны, а не Generics, как в C#.
pu4koff вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Циклы и константы romanzi Общие вопросы Delphi 4 24.08.2011 11:36
Константы romantik2011 PHP 1 07.08.2011 06:12
С++ константы Filipa Помощь студентам 2 06.01.2011 00:27
Константы veter48 Общие вопросы C/C++ 10 14.09.2010 21:03
Константы с U, L и F Smarti Общие вопросы C/C++ 5 01.09.2010 23:38