Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Шаблоны функций  (Прочитано 11852 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Olegator
Команда клуба

ru
Offline Offline
Пол: Мужской

« : 05-01-2006 23:28 » 

Не пойму я один момент.
Вот допустим шаблон, который находит максимальный из трёх аргументов.
Код:
//  Использование  шаблонов  функций
#include  <iostream.h>
template  <class  T>
T  maximum(T  valuel,  T  value2,  T  value3)
{
   T max  =  valuel;
   if  (value2  > max) max  = value2;
   if  (value3  > max) max  = value3;
   return max;
}
Получается функция совершает одни и те же действия к аргументам любого типа.
Я могу подставить int double char
Но ведь тип может быть таким, что нельзя их сравнить, какой меньше какой больше.
Т.е. должен быть какой-то кантроль типов. Должно быть так, что какие-то типы можно использовать, а какие-то нет.
Записан
nikedeforest
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #1 : 05-01-2006 23:32 » 

Цитата
Я могу подставить int double char
Не можешь, class T только один. Поэтому либо везде int или double или char и т.п.
Для того, что бы разные типы были надо, чтобы еще был class T1 к примеру.
Записан

ещё один вопрос ...
nikedeforest
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #2 : 05-01-2006 23:38 » 

Сейчас перечитал и думаю я кажется ответил не совсет на то, что ты спрашивал.
Контроль типов программист осуществляет сам. Для этого есть механизм RTTI или по другому механизм динамической идентификации типов.
Записан

ещё один вопрос ...
Olegator
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #3 : 05-01-2006 23:41 » 

Сейчас перечитал и думаю я кажется ответил не совсет на то, что ты спрашивал.
А я только хотел тебе об этом написать:
Это я понял.
Я спросил про другое.
Допустим есть тип type1
type1 a, b, c;
Я вызываю функцию:
maximum(a,b,c);
Но между a b и с нельзя поставить знаки <, > или =
Тогда как?
Записан
Alf
Гость
« Ответ #4 : 05-01-2006 23:44 » 

Конечно, не все типы можно сравнивать между собой. Поскольку у тебя используется оператор сравнения ">", ты должен использовать либо встроенные типы, для которых эта операция уже определена, или же в твоем классе следует ее определить:

Код:
class C
{
...
  bool operator>(const C& c);
...
};

Без этого возникнет ошибка при попытке использования в качестве аргумента шаблона класса, для которого не определено сравнение.
Записан
Olegator
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #5 : 05-01-2006 23:51 » 

Это не приводит к уменьшению надёжности, если теперь типы придёться контролировать мне, а не компилятору?
Записан
Alf
Гость
« Ответ #6 : 05-01-2006 23:58 » 

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

Раскрывая шаблон, компилятор просто сгенерирует строку вида

Код:
   if  (value2  > max) max  = value2;

Если value2 и max принадлежат к некоторому типу T (как следует из твоего шаблона), для которого определены операторы сравнения и присваивания, никакого уменьшения надежности тут нет в помине. Конечно, можно наделать ошибок при переопределении операторов, но это другая тема.
Записан
Olegator
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #7 : 06-01-2006 00:11 » 

Т.е. и просто функцию я могу написать неправильно. В этом отношении функция и шаблон равны.

Контроль типов программист осуществляет сам. Для этого есть механизм RTTI или по другому механизм динамической идентификации типов.
А это к чему?
Записан
nikedeforest
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #8 : 06-01-2006 00:18 » 

Это уже не в тему получается. Просто этот механизм позволяет контролировать тип переменой к примеру. Т.е. ты можешь удостовериться, что это тип int, а не double или узнать/проверить тип созданного объекта. Также с помощью этого механизма ты можешь провести динамическое приведение типа с дальнейшей проверкой на корректность привидения. Можно провести замещение модификатора const и т.п.
Записан

ещё один вопрос ...
Alf
Гость
« Ответ #9 : 06-01-2006 00:25 » 

Просто этот механизм позволяет контролировать тип переменой к примеру. Т.е. ты можешь удостовериться, что это тип int, а не double или узнать/проверить тип созданного объекта.

Можно пример, каким образом я смогу отличить int от double?
Записан
nikedeforest
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #10 : 06-01-2006 00:37 » 

Цитата
Можно пример, каким образом я смогу отличить int от double?
Да, конечно.
Код:
#include <iostream>
#include <typeinfo>
using namespace std;

int main()
{

int i;
float f;
char *p;
cout<<"Тип переменной i:"<<typeid(i).name();
cout<<endl;
cout<<"Тип переменной f:"<<typeid(f).name();
cout<<endl;
cout<<"Тип переменной p:"<<typeid(p).name();
cout<<endl;

return 0;
}

Результат:
Цитата
Тип объекта i:int
Тип объекта f:float
Тип объекта p:char *
Записан

ещё один вопрос ...
Alf
Гость
« Ответ #11 : 06-01-2006 00:46 » 

Это все здорово, конечно, но... Я ведь и сам отлично знаю типы i, f и p, поскольку их можно определить на этапе компиляции. Компилятор говорит мне то, что я сам ему только что сказал в исходнике. Тема динамического определения типа не раскрыта.
Записан
nikedeforest
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #12 : 06-01-2006 01:24 » 

Alf, ты ведь и не просил раскрыть тему, ты попросил привести пример, я привел.
А по поводу темы, попробую раскрыть, хотя непопулярность (даже я бы сказал неизвестность) RTTI говорит о том, что без него легко обходятся и этот механизм не является каким-то необходимейшим средством.
Возьмем к примеру шаблоны, здесь же вполне может пригодиться идентификация типа.
RTTI не только распознает типы, но и позволяет производить динамическое приведение типов. При этом есть выбор об осуществлении проверки корректности или об ее отмене. Вполне полезным может оказаться замещение модификатора const (а может это никогда не применится за всю жизнь).
RTTI позволяет преобразовать один тип в совершенно другой, к примеру приведение указателя к цешлому цислу. Не знаю где это может пригодится, а с другой стороны всего не предусмотришь.
Возможности перечислил, а уж где применить это каждый сам себе хозяин. У меня опыта нет (авось в будущем сгодится), тебе виднее где это применить, а может и вообще нигде. Думаю, полезно иметь на вооружении, как я уже говорил -  всего не предусмотришь.
зы: темы раскрыть не получилось Улыбаюсь, значит не судьба Улыбаюсь.
Записан

ещё один вопрос ...
Alf
Гость
« Ответ #13 : 06-01-2006 01:34 » 

Динамическое приведение имеет смысл в случае полиморфизма, когда есть необходимость сделать downcast (хотя IMHO это не есть хороший тон в программировании). Привести указатель к целому можно статически через reinterpret_cast (хотя это хакерство и вряд ли имеет смысл в нормальных программах). А вот зачем приводить динамически скалярные типы друг в друга - ума не приложу. Надеялся, что тебе известны практические применения подобных трюков, потому и попросил пример.
Записан
nikedeforest
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #14 : 06-01-2006 01:39 » 

Цитата
Привести указатель к целому можно статически через reinterpret_cast (хотя это хакерство и вряд ли имеет смысл в нормальных программах).
Вроде как средство-то (я про reinterpret_cast )стандартизировано, почему хакерство?
Цитата
Надеялся, что тебе известны практические применения подобных трюков, потому и попросил пример.
Да ну, хватит тебе. С моим опытом-то. Давай к этому лет через 15-20 вернемся Улыбаюсь, хотя не стоит зарекаться.
Честно говорю, понятия не имею где это можно применить, хотя  интересно.
Записан

ещё один вопрос ...
Alf
Гость
« Ответ #15 : 06-01-2006 02:03 » 

Вроде как средство-то (я про reinterpret_cast )стандартизировано, почему хакерство?

Потому как не вижу особо полезных применений данного трюка. Разве что для операционных систем (а многие ли из нас пишут операционные системы?). Или же вирусов (а этим товарищам вообще ноги выдергивать нужно). Его применение дает сложный в чтении, подверженный ошибкам и зависимый от реализации код, а это и есть хакерство в худшем смысле.

Сам папа Страуструп говорит следующее:

Цитата
Некоторые преобразования static_cast являются переносимыми, но reinterpret_cast практически никогда не переносимо. Хотя никаких гарантий относительно reinterpret_cast дать нельзя, в результате обычно получается значение нового типа, состоящее из той же цепочки битов, что и аргумент преобразования.

Вот такая прелестная конструкция - что-то вроде мартышки с гранатой, неизвестно, что выйдет в результате. Если уж сам Создатель говорит, что гарантий дать не может, но возможно, получится вот что... Ага
Записан
Alf
Гость
« Ответ #16 : 06-01-2006 02:09 » 

С моим опытом-то. Давай к этому лет через 15-20 вернемся Улыбаюсь

Я же не говорю, что непременно ты сам эти фокусы изобрести должен. Мог наткнуться на статью интересную или книгу. Я же не могу все на свете перечитать, что-то упустил непременно (а по С++ вообще почти ничего не читаю последние пару-тройку лет).
Записан
nikedeforest
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #17 : 06-01-2006 02:10 » 

А чем вызвано появление reinterpret_cast, известно? Должна же быть весомая причина на создание такого сомнительного "сервиса" (не смог лучше сконструировать предложение).
Цитата
Мог наткнуться на статью интересную или книгу.
Увы, нет. Я пока что не читаю литературу по алгоритмам. Пока изучаю инструменты и возможности (язык, API и т.п.).
« Последнее редактирование: 06-01-2006 02:13 от nikedeforest » Записан

ещё один вопрос ...
Alf
Гость
« Ответ #18 : 06-01-2006 02:21 » 

А чем вызвано появление reinterpret_cast, известно? Должна же быть весомая причина на создание такого сомнительного "сервиса" (не смог лучше сконструировать предложение).

Я так думаю, это следствие неудержимого стремления папы Страуструпа угодить и вашим, и нашим. Он пытался на каркасе низкоуровневого языка С построить современный (в то время) объектно-ориентированный язык и при этом сохранить 100% языковую совместимость с С (на самом деле получилось примерно 99.9%, что тоже весьма немало), а также не потерять в эффективности исполняемого кода. А компромисс никогда не приводит к совершенству. В результате имеем нагромождение парадигм и стилей, одно и то же можем делать разными способами. Кому-то нравится, а лично мне не импонирует неоднозначность, это не музыка и не литература, где импровизация только на пользу.

Примерно то же самое имеем и в железе от Intel, когда разработчикам не хватило решимости отказаться от древней 16-битной архитектуры с сегментной адресацией, и они волокут эту тяжкую ношу уже пару десятков лет ради давно никому не нужной совместимости с давно забытым процессором 8086. Не зря же современные RISC-процессоры уделывают Пентиумы играючи, у них на кристалле ничего лишнего, а то, что есть, вылизано до предела.
Записан
nikedeforest
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #19 : 06-01-2006 02:31 » 

Цитата
Кому-то нравится, а лично мне не импонирует неоднозначность, это не музыка и не литература, где импровизация только на пользу.
Твое глубокое знание С/С++ заставляло меня делать выводы, что ты предпочитаешь использовать именно этот язык (С++). Теперь  непонятно, какой же язык ты предпочитаешь?
Записан

ещё один вопрос ...
Alf
Гость
« Ответ #20 : 06-01-2006 02:42 » 

Я предпочитаю C# и Java. С точки зрения собственно языка мне интереснее C#, особенно его недавняя вторая версия. Java несколько консервативнее, зато весьма мобилен и, что немаловажно после того, как российские чиновники продались глобалистам, он бесплатен. То есть если меня вытеснят на Linux, 99.9% вероятности, что я перейду на Java.

Оба эти языка весьма цельны и хорошо продуманы. То, что из них изъято, в подавляющем большинстве случаев не требуется при прикладном программировании, а то, что оставлено, тщательно отшлифовано. На первый взгляд может показаться, что некоторые ограничения связывают руки. На самом деле это преувеличение. Я бы привел такое сравнение - это все равно, что утверждать, будто гитара ограниченнее скрипки, поскольку на ней есть лады, а на скрипке звукоряд фактически непрерывен. Однако любой гитарист знает, что за счет бенда или движения рычагом вибратора он легко обходит эти ограничения. Примерно так же и здесь.
Записан
nikedeforest
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #21 : 06-01-2006 02:57 » 

Понятно, правда с гитарой и скрипкой у меня проблемы Улыбаюсь, несмотря на начальное музыкальное образование, но это я так, шутки ради.
const_cast использовал хоть раз? Мне что-то интересно стало,пытаюсь делать так:
Код:
const int k=2;
const_cast<int>(k)=3;
Ругается на меня
Цитата
cannot convert from 'const int' to 'int'
Или я вообще не так его использую?
« Последнее редактирование: 20-12-2007 17:55 от Алексей1153++ » Записан

ещё один вопрос ...
Alf
Гость
« Ответ #22 : 06-01-2006 17:01 » 

Ругается на меня
Цитата
cannot convert from 'const int' to 'int'
Или я вообще не так его использую?

Смотри MSDN:

Цитата
The const_cast operator can be used to remove the const, volatile, and __unaligned attribute(s) from a class.

A pointer to any object type or a pointer to a data member can be explicitly converted to a type that is identical except for the const, volatile, and __unaligned qualifiers.
...
You cannot use the const_cast operator to directly override a constant variable's constant status.

Полагаю, нужно иметь весьма веские основания на то, чтобы по ходу менять значения констант. Сам никогда не применял это преобразование и не припомню случая, когда это оказалось бы полезным. Это скорее может пригодиться при латании чужого кода, когда прежний разработчик счел нужным объявить объект константным, а потом оказалось, что он все же иногда меняет значение. Лучше все-таки перепроектировать подобные сомнительные случаи, чем латать их подобным образом.
« Последнее редактирование: 20-12-2007 17:56 от Алексей1153++ » Записан
Olegator
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #23 : 08-01-2006 01:26 » 

И всё-таки мне не понятно.
Здесь о чём написано:
Цитата
Прототип функции указывает компилятору тип данных, возвращаемых функцией, количество параметров, которое ожидает функция, тип параметров и ожидаемый порядок их следования. Компилятор использует прототип функции для проверки правильности вызовов функции. Ранние версии С не выполняли такого рода проверку, поэтому был возможен неправильный вызов функции без обнаружения ошибок компилятором. Подобные вызовы приводили к неисправимым ошибкам выполнения или к хитроумным исправимым логическим ошибкам, которые было очень трудно обнаружить. Прототипы функции устранили этот недостаток.
О том, что я могу в функцию подставить только то количество аргументов которое указано в прототипе. Порядок следования. В этом шаблон и прототип, равны.
Но проверка типов аргументов на совпадение с типами параметров отсутствует, потому что я могу подставить любой тип.
Записан
Alf
Гость
« Ответ #24 : 08-01-2006 01:34 » 

Для каждого возможного типа, который ты подставляешь в шаблон, у тебя генерируется отдельная функция со своей сигнатурой. Процитированное тобой остается верным для каждой из этих функций.
Записан
Olegator
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #25 : 08-01-2006 01:48 » 

Я всё понял, но у меня всё время ощущение, что с этими шаблонами есть какая-то проблема. Ты скажи, есть проблема или нет?
« Последнее редактирование: 08-01-2006 06:11 от Olegator » Записан
Alf
Гость
« Ответ #26 : 08-01-2006 01:56 » 

"Есть человек - есть проблема..." (С) Лучший Друг Советских Программистов

Любой предмет, в котором плаваешь, превращается в неиссякаемый источник проблем. Выучи как следует матчасть - проблемы устранятся сами собой.

В конце концов, шаблоны придуманы в помощь программистам, а не для самоистязаний садомазохистам. Их умелое применение может изрядно облегчить жизнь. По крайней мере, в C# первой версии их очень даже не хватало.
Записан
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines