Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Шаблоны в C++

11
10 ноября 2010 года
oxotnik333
2.9K / / 03.08.2007
Вопрос скорее идиотский, поэтому задам в общалке.
О том, что шаблоны вещь нужная и полезная распространяться много не буду, это и так ясно, с одной стороны... а с другой, в каких реальных задачах их необходимо применять, т.е. без них не обойтись? Мне пока хватало классического ООП без шаблонов. Под "применять" я имею ввиду самому разрабатывать, а не использовать готовые STL/boost.
Страницы:
341
13 ноября 2010 года
Der Meister
874 / / 21.12.2007
Обоим авторам примеров о физике нужно срочно завести подружек. Метакод на шаблонах - жесть, но приведённый - вообще субметакод какой-то, тут реально кодсмит на него нужен. Код на Nemerle меня порадовал лишь модулем UnitDef.n, в остальном его логика мне едва ли более очевидна для разбора "с ходу" без отладчика, чем шаблоны. Меня терзает вопрос: какова цель и объём проекта, в котором для относительно простой подзадачи, полезность решения которой для меня лично вообще сомнительна, оправдывается применение столь "дорогих" решений?
297
13 ноября 2010 года
koodeer
1.2K / / 02.05.2009
Цитата: Der Meister
Меня терзает вопрос: какова цель и объём проекта, в котором для относительно простой подзадачи, полезность решения которой для меня лично вообще сомнительна, оправдывается применение столь "дорогих" решений?


А чем оно дорого? Автор кода на Nemerle за два дня его написал, по его словам. Потом ещё несколько раз подправлял. Несколько дней - не так уж дорого на код, который потом может использоваться годами.

Лично для меня полезность такого кода очевидна: ведь это здорово, когда компилятор сразу предупреждает об ошибках. Гораздо хуже, если для вылова таких ошибок приходится писать юнит-тесты и всячески мучиться.

Я являюсь поклонником статической типизации, и крайне негативно отношусь даже к тому, что какие-нибудь параметры задаются в виде строк, как например строки формата в операторах типа printf. Такие строки не проверяются компилятором (в Nemerle, впрочем, проверяются), что считаю плохо.

Имхо, механизм задания типам условий, разрешающих/запрещающих их участие в операциях с другими типами мог бы сильно уменьшить количество ошибок. Будь оно встроено изначально в язык, я бы активно пользовался. Уверен: пользовались бы многие. Не пользуются лишь потому, что этого пока нигде нет. Эти два примера с rsdn - первые ласточки.


Цитата: Der Meister
Код на Nemerle меня порадовал лишь модулем UnitDef.n, в остальном его логика мне едва ли более очевидна для разбора "с ходу" без отладчика, чем шаблоны.


Ну, логика какого-нибудь специализированного сильно-оптимизированного кода тоже не очевидна с ходу. Но зачем в нём разбираться? Им нужно пользоваться!

341
13 ноября 2010 года
Der Meister
874 / / 21.12.2007
Цитата: koodeer
А чем оно дорого? Автор кода на Nemerle за два дня его написал, по его словам. Потом ещё несколько раз подправлял. Несколько дней - не так уж дорого на код, который потом может использоваться годами.

На введение доменов для пяти численных величин в трёх выражениях тратить два дня - вот я и говорю о подружке.

Цитата: koodeer
Лично для меня полезность такого кода очевидна: ведь это здорово, когда компилятор сразу предупреждает об ошибках. Гораздо хуже, если для вылова таких ошибок приходится писать юнит-тесты и всячески мучиться.

Правильность формул проверяется аналитиком с использованием соответствующих инструментов, а не компилятором. Модульное тестирование же необходимо в любом случае.

Цитата: koodeer
Я являюсь поклонником статической типизации, и крайне негативно отношусь даже к тому, что какие-нибудь параметры задаются в виде строк, как например строки формата в операторах типа printf. Такие строки не проверяются компилятором (в Nemerle, впрочем, проверяются), что считаю плохо.

В Basic тоже проверяются. Макры Nemerle - да, весело, я ж не спорю. Тяжёлый случай порадовал возможностью генерировать винформы на C# в проектах Nemerle - и это действительно круто. Но конкретно данную задачу в рантайме я бы решил по паттерну Money, где вместо банка выступала бы система измерения. И никаких проблем: надо ускорение - просим ускорение. Умножаем на время - получаем скорость. Надо в системе СИ - сворачиваем выражение с коэффициентами из СИ. Это займёт минут 30.
Если у меня бешеные тыщи формул и мне нужно посчитать их в компайл-тайме - я посчитаю их в Maple и сгенерирую код.

Цитата: koodeer
Имхо, механизм задания типам условий, разрешающих/запрещающих их участие в операциях с другими типами мог бы сильно уменьшить количество ошибок. Будь оно встроено изначально в язык, я бы активно пользовался. Уверен: пользовались бы многие. Не пользуются лишь потому, что этого пока нигде нет. Эти два примера с rsdn - первые ласточки.

Не люблю не понимать: разве хотя бы в C++, с его вездесущими неявными преобразованиями типов, есть правила, разрешающие любым типам участвовать в операциях с любыми другими типами?

Цитата: koodeer
Ну, логика какого-нибудь специализированного сильно-оптимизированного кода тоже не очевидна с ходу. Но зачем в нём разбираться? Им нужно пользоваться!

Ну так какая тогда здесь показательная разница между шаблонами и макрами, если не смотреть в зубы реализации?

297
13 ноября 2010 года
koodeer
1.2K / / 02.05.2009
Цитата: Der Meister
На введение доменов для пяти численных величин в трёх выражениях тратить два дня


Ну почему в трёх выражениях? Ведь этот код теперь можно использовать в любых крупных проектах с тысячами выражений. И автоматически будет отслеживаться их правильность.

Цитата: Der Meister
Правильность формул проверяется аналитиком с использованием соответствующих инструментов, а не компилятором.


Зарплата аналитику - вот это дорого ;). Компилятор работает бесплатно ;).

Цитата: Der Meister
Если у меня бешеные тыщи формул и мне нужно посчитать их в компайл-тайме - я посчитаю их в Maple и сгенерирую код.


Хорошо. С этим согласен. Но если для предметной области нет специализированного софта, наподобие Maple? Или он проприетарен и дорог?

Цитата: Der Meister
Не люблю не понимать: разве хотя бы в C++, с его вездесущими неявными преобразованиями типов, есть правила, разрешающие любым типам участвовать в операциях с любыми другими типами?


Например, температура имеет тип double, масса имеет тип double. Компилятор позволит сложить эти величины, в то время как с физической точки зрения это не имеет смысла.

Цитата: Der Meister
Ну так какая тогда здесь показательная разница между шаблонами и макрами, если не смотреть в зубы реализации?


Я не о разнице между шаблонами и макрами, я о том, что этим написанным кодом уже можно пользоваться (хоть в C++, хоть в Nemerle), и это потенциально убережёт от некоторых ошибок.


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

341
13 ноября 2010 года
Der Meister
874 / / 21.12.2007
Цитата: koodeer
Ну почему в трёх выражениях? Ведь этот код теперь можно использовать в любых крупных проектах с тысячами выражений. И автоматически будет отслеживаться их правильность.

Вот и сомневаюсь: оправдан ли этот код популярностью задачи об абстрактной арифметике с произвольными величинами в компайл-тайме? Ну то есть обычно есть готовая матмодель, по которой строится реализация. Иными словами, формулы уже готовы, их не нужно проверять компилятором, а уж тем более выводить размерность в программе. Для символьной арифметики есть специализированные матпакеты и библиотеки. Зачем этот пугающий код?
Кроме того, для любого выражения здесь, кажется, должна быть величина, описывающая его размерность. Тогда "выносить за скобки" и прочая средства повышения выразительности (расчитывать заранее результаты вспомогательных выражений а-ля дискриминант в реквуре) применять будет затруднительно (поправьте, пожалуйста, если неправ).

Цитата: koodeer
Зарплата аналитику - вот это дорого ;). Компилятор работает бесплатно ;)

Так даже если вы и программист и аналитик в одном лице, вы ж всё равно формулы на бумажке выводите, не так ли? Правильность размерности не говорит о правильности формул, так что результат всё равно надо тестировать - и проверочными формулами, и результатом.

Цитата: koodeer
Хорошо. С этим согласен. Но если для предметной области нет специализированного софта, наподобие Maple? Или он проприетарен и дорог?

Этот софт наверняка будет дешевле (не только в $-эквиваленте), чем дублирующий его функциональность метакод.

Цитата: koodeer
Например, температура имеет тип double, масса имеет тип double. Компилятор позволит сложить эти величины, в то время как с физической точки зрения это не имеет смысла.

Эта задача решается обсуждаемым кодом так: для каждой величины вводится домен (тип), правильность контролируется совпадением типов. Однако домены тут неполноценны: нет и нельзя добавить контроль правильности значений, нельзя описать операции, специфичные для каждой конкретной величины. Я предложил просто завести домены ручками (+ домен, описывающий выражения), это снимет вышеописанные ограничения и займёт гораздо меньше времени - вот и всё. То есть будут просто конкретные типы Temperature и Mass и там, где нужны соответствующие величины, они и будут требоваться.

Цитата: koodeer
Я не о разнице между шаблонами и макрами, я о том, что этим написанным кодом уже можно пользоваться (хоть в C++, хоть в Nemerle), и это потенциально убережёт от некоторых ошибок.

Так а я-то о том, что в обоих случаях код ужасен :)

87
14 ноября 2010 года
Kogrom
2.7K / / 02.02.2008
Цитата: Нездешний
Неплохо было бы еще маааленький конкретный примерчик :) Причем не чисто теоретический, а полезный



"Маааленький" в виде кода не получится, тут надо на словах понимать. Например, есть у нас некий класс от стороннего произовдителя, реализующий работу COM-порта (или того же CAN). А мы хотим позволить пользователю работать с программой в режиме эмулятора, когда нужное железо не подключено. Делаем класс-заглушку, который имитирует работу нашего железа.

Наследоваться напрямую - неудобно и чревато. Во первых, придется переопределять все функции. Во вторых, в исходном классе могут остаться нежелательные обращения к железу в конструкторе и деструкторе, например.

Чтобы обеспечить полиморфизм, мы можем писать много писем, чтобы авторы отнаследовали свой класс от определённого абстрактного, а можем извернуться через шаблоны. При том, при использовании шаблонов можно заинкапсулировать все ненужные открытые методы.

Хотя, в общем, тут я пример преимуществ композиции более, чем шаблонов...

297
14 ноября 2010 года
koodeer
1.2K / / 02.05.2009
Цитата: Der Meister
Я предложил просто завести домены ручками (+ домен, описывающий выражения), это снимет вышеописанные ограничения и займёт гораздо меньше времени - вот и всё.


А можно примерчик? На любом языке, можно на псевдокоде. Или ссылку.

Цитата: Der Meister
То есть будут просто конкретные типы Temperature и Mass и там, где нужны соответствующие величины, они и будут требоваться.


То есть сделать классы Temperature и Mass? Нет, меня такое не устраивает: это даст резкое снижение производительности, ведь понадобятся конструкторы копирования и прочее, то есть много работы будет в рантайме! Те два примера на rsdn делают проверки в компайл-тайме, а сами величины были и остаются простыми типами (int, double и т. п.)

Цитата: Der Meister
Так а я-то о том, что в обоих случаях код ужасен :)


Да хрен с ним, пусть ужасен. Может, Maple внутри тоже ужасен. Нам это не мешает его использовать в своих личных корыстных целях.
И, кстати, сдаётся мне, что на создание Maple было потрачено гораздо больше двух дней. Но пользователям-то это без разницы: главное, им теперь можно пользоваться.
Если бы все программеры только о девушках думали, то не было бы ни опен сорса, ни многого другого.

Цитата: Der Meister
Ну то есть обычно есть готовая матмодель, по которой строится реализация. Иными словами, формулы уже готовы, их не нужно проверять компилятором, а уж тем более выводить размерность в программе. Для символьной арифметики есть специализированные матпакеты и библиотеки. Зачем этот пугающий код?


Допустим, британский учёный хочет просчитать развитие популяции карасей в пруду в зависимости от курса шекеля и фазы Луны. Есть для этого специализированный софт? Не думаю. А с помощью тех библиотек можно задать поведение любых простых типов. И уже нельзя будет приплюсовать карасей к малиновым крокодильчикам - компилятор не даст.

Видимо, я никак не могу объяснить то, чем меня так привлекла эта возможность.
Для чего придумали ООП? Чтобы можно было в программах использовать не биты/байты, не простые типа данных - целые и вещественные числа, - а сущности реального мира. Хочешь, класс Person создаёшь, описывающий человека, хочешь ещё что. Но этот путь имеет большой недостаток: размер кода получается большим, процессорного времени на работу с классами тратится много.
А тут я внезапно узрел то, о чём мог только мечтать: создаются внешне новые типы данных, с говорящими именами, с чётко заданным поведением, но на самом деле они остаются простыми числами. И вычисления с ними мгновенны.

К сожалению, прошло уже несколько лет, как появились те примеры на rsdn, а ими, похоже, никто особо не загорелся. Думаю, тут дело в инертности. Вот если нечто подобное будет введено в мэйнстримовый язык крупной корпорацией (скажем Microsoft в С++ и C#), то это вызовет волну восторгов: как мы раньше могли жить без этого, ведь это так удобно!

5
15 ноября 2010 года
hardcase
4.5K / / 09.08.2005
Цитата: koodeer
Вот если нечто подобное будет введено в мэйнстримовый язык крупной корпорацией (скажем Microsoft в С++ и C#), то это вызовет волну восторгов: как мы раньше могли жить без этого, ведь это так удобно!

TypeProviders появятся в будущей версии F# (может Дон Сайм не знает о макросах?).

87
15 ноября 2010 года
Kogrom
2.7K / / 02.02.2008
Некоторые размышления по поводу той системы с переводом одних единиц в другие (http://www.rsdn.ru/forum/src/1824757.flat.aspx).

Интересные особенности:

1. Наиболее интересной мне показалась таблица расчёта типов (она идёт в самом начале). Она используется для вычисления типа формулы. Например, тип выражения расстояние/время должен быть типом скорости.

2. Второстепенной особенностью является автоматический расчёт коэффициентов перевода из одной системы в другую.

Замечания по использованию:

1. Думаю, область использования этой идеи довольно узка. Например, страшновато тут использовать величины, соотношения которых меняется хотя бы раз в год, ибо много ручной работы, требующей внимательности. Например, курсы валют так рассчитывать не будешь - велик риск запутаться.
2. Хорошо, если системы единиц можно пересчитать по формуле y = a*x. Если же формулы будут сложнее, даже y = a*x + b, то реализация намного усложнится или вообще будет невозможна.
3. Есть ещё мелочь, на которую не обращают герои - время компиляции (перекомпиляции). Если оно будет велико - то неудобно будет применять технологию маленьких шажков.
4. Ну и замечу, что это опять был пример применения шаблонах в библиотеках, которые меняются раз в сто лет. Это созвучно с пунктом 1.

Замечания к реализации.

1. Больше всего меня смущает функция pow в конструкторе. Как показывает практика, это сравнительно медленная функция (учитывая, что в степени может быть не целое число). А если определённый компилятор не сможет её рассчитать во время компиляции, то половина этих плясок будет зря.

2. Есть много однообразного кода. Но как решить это - не могу сказать. Хотя, можно было бы многое сократить простыми сишными макросами. Возможно, тут они уместны.
5
15 ноября 2010 года
hardcase
4.5K / / 09.08.2005
Цитата: Kogrom

2. Есть много однообразного кода. Но как решить это - не могу сказать. Хотя, можно было бы многое сократить простыми сишными макросами. Возможно, тут они уместны.



Тут уместна машина вывода. Нашел таки не слишком давнее обсуждение подобной темы на RSDN. Ищите в топике упоминание Z3.

353
19 ноября 2010 года
Nixus
840 / / 04.01.2007
Несколько примеров использования шаблонов.

1. Статические ассерты.
 
Код:
template<bool> struct cCompileTimeError;
template<> struct cCompileTimeError<true> {};
                                                                               
#define staticCheck( expr, msg ) \
        { cCompileTimeError< ((expr) != 0) > ERROR_##msg;(void)ERROR_##msg; }

Пример использования:
 
Код:
staticCheck( sizeof(byte ) == 1, Size_Of_Byte_Is_Not_1 );


2. Характеристики (traits).
Примеры были приведены. Тут просто огромный простор для использования.

3. Автоматическое создание синглтонов.
 
Код:
template< class T > inline T& single() {
    static T object;
    return object;
}

single<SomeClass>().doSomething();
...
single<SomeClass>().doSomethingelse();


Сколько бы мы не вызывали single<SomeClass>() будет возвращена ссылка на один и тот же объект. При этом он будет создан при первом вызовы.

Если недостаточно могу вспомнить еще.
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог