Compile-time vs. Runtime полиморфизм
От: Курилка Россия http://kirya.narod.ru/
Дата: 20.10.04 09:06
Оценка:
Собственно общался тут с коллегами по поводу двойной диспетчеризации (double-dipatching), ну они говорят — в C++ лучше запихать это дело в шаблоны, будет гораздо быстрее и меньше ошибок в рантайме.
Соответственно 2 вопроса:
какие плюсы и минусы шаблонов против "традиционной" реализации посредством 2 vtbl?
И вообще — можно ли совсем заменить полиморфизм и виртуальные функции шаблонами.
Т.е. интересуют ситуации более выгодные для полиморфизма в compile-time и полиморфизма "настоящего", т.е. посредством виртуальных функций и vtbl?
Буду рад любым мнениям (даже помидорам в мою сторону)

P.S. коллеги плюсовики, а я в данный момент занимаюсь дельфи, где шаблонов нема, увы...
Re: Compile-time vs. Runtime полиморфизм
От: GlebZ Россия  
Дата: 20.10.04 10:38
Оценка: 4 (1)
Здравствуйте, Курилка, Вы писали:

К>Собственно общался тут с коллегами по поводу двойной диспетчеризации (double-dipatching), ну они говорят — в C++ лучше запихать это дело в шаблоны, будет гораздо быстрее и меньше ошибок в рантайме.

К>Соответственно 2 вопроса:
К>какие плюсы и минусы шаблонов против "традиционной" реализации посредством 2 vtbl?
К>И вообще — можно ли совсем заменить полиморфизм и виртуальные функции шаблонами.
К>Т.е. интересуют ситуации более выгодные для полиморфизма в compile-time и полиморфизма "настоящего", т.е. посредством виртуальных функций и vtbl?
Сравнение разного функционала. Шаблоны преследуют цель инкапсулировать некоторый алгоритм или набор алгоритмов в классе, который применяются к нескольким другим классам, не обязательно связанными общим предком. Выполняется только на этапе компиляции. Наследование и позднее связывание — наследование общих интерфейсов от наследованных классов, и определение этих интерфейсов на этапе выполнения. То есть, в первом случае, мы имеем класс отвечающий за некоторый алгоритм, имеющий свой собственный интерфейс определяемый только на этапу компиляции, который компилируется в объект отвечающий за реализацию алгоритма для конкретного типа класса. И соответсвенно, Alg<class 1> и Alg<class 2> совершенно различные типы. Во втором случае, мы получаем объект реализующий свойства, имеющий некоторую библиотеку типов (интерфейсов) которые можно идентифицировать в Runtime. Например, если посмотреть на паттерн Composite, то такие вещи возможны только при использовании наследования, в котором возможна идентификация интерфейсов.

Также говорят что наследование некоторое отступления от полиформизма, так как наследуемый объект предоставляет свои внутренние свойсва для наследников.

С уважением, Gleb.
Re[2]: Compile-time vs. Runtime полиморфизм
От: Курилка Россия http://kirya.narod.ru/
Дата: 20.10.04 10:48
Оценка:
Здравствуйте, GlebZ, Вы писали:

GZ>Здравствуйте, Курилка, Вы писали:


К>>Собственно общался тут с коллегами по поводу двойной диспетчеризации (double-dipatching), ну они говорят — в C++ лучше запихать это дело в шаблоны, будет гораздо быстрее и меньше ошибок в рантайме.

К>>Соответственно 2 вопроса:
К>>какие плюсы и минусы шаблонов против "традиционной" реализации посредством 2 vtbl?
К>>И вообще — можно ли совсем заменить полиморфизм и виртуальные функции шаблонами.
К>>Т.е. интересуют ситуации более выгодные для полиморфизма в compile-time и полиморфизма "настоящего", т.е. посредством виртуальных функций и vtbl?
GZ>Сравнение разного функционала. Шаблоны преследуют цель инкапсулировать некоторый алгоритм или набор алгоритмов в классе, который применяются к нескольким другим классам, не обязательно связанными общим предком. Выполняется только на этапе компиляции. Наследование и позднее связывание — наследование общих интерфейсов от наследованных классов, и определение этих интерфейсов на этапе выполнения. То есть, в первом случае, мы имеем класс отвечающий за некоторый алгоритм, имеющий свой собственный интерфейс определяемый только на этапу компиляции, который компилируется в объект отвечающий за реализацию алгоритма для конкретного типа класса. И соответсвенно, Alg<class 1> и Alg<class 2> совершенно различные типы. Во втором случае, мы получаем объект реализующий свойства, имеющий некоторую библиотеку типов (интерфейсов) которые можно идентифицировать в Runtime. Например, если посмотреть на паттерн Composite, то такие вещи возможны только при использовании наследования, в котором возможна идентификация интерфейсов.

Сенкс за пример!
Т.е. имеем в случае шаблонов — больший объём бинарника, а в случае наследования — накл. расходы, связанные с vtbl?
Не говоря о невозможности нек. конструкций в 1-м или 2-м подходах...

GZ>Также говорят что наследование некоторое отступления от полиформизма, так как наследуемый объект предоставляет свои внутренние свойсва для наследников.


Т.е. от полиморфизма с т.зр. ФП? Где тот же sort может быть для всех типов без никаких ограничений на тип объектов?
Не знаешь, а есть где-нибудь строгое определение полиморфизма как такогого, ну и рассмотрение разн. вариантов было бы также интересно
Re: Compile-time vs. Runtime полиморфизм
От: eugals Россия  
Дата: 20.10.04 11:07
Оценка: 4 (1)
Здравствуйте, Курилка, Вы писали:

<...>
[ИМХО]
Главный плюс позднего связывания в сокрашении зависимостей между модулями.
Для использования варианта с шаблонами, клиентская сторона должна знать про все классы, над которыми она собирается учинить полиморфное использование. Причем, она должна знать ещу и про все классы, которые являются свойствами этих классов, и про свойства свойств и т.д.

Если в случае отдельного пакета это себе ещё можно позволить, то для выстраивания межпакетного интерфейсы я бы всё-таки предпочел vtbl
[/ИМХО]
... << RSDN@Home 1.1.4 beta 2 >>
Re[2]: Compile-time vs. Runtime полиморфизм
От: Курилка Россия http://kirya.narod.ru/
Дата: 20.10.04 11:11
Оценка:
Здравствуйте, eugals, Вы писали:

E>Здравствуйте, Курилка, Вы писали:


E><...>

E>[ИМХО]
...
E>[/ИМХО]

моё ХО тут может только согласиться
Re: Compile-time vs. Runtime полиморфизм
От: Кодт Россия  
Дата: 20.10.04 11:54
Оценка: 8 (1)
Здравствуйте, Курилка, Вы писали:

<>

Это из серии "что лучше, трактор или самолёт".

run-time-полиморфизм требует
* затрат на его поддержку (память под vtbl, vptr или аналогичные рукоделия; время на косвенный вызов; косвенный доступ к данным)
* бОльшей строгости интерфейсов (поскольку структура vtbl прибита гвоздями)

Чистый compile-time полиморфизм, в свою очередь, требует, чтобы типы были известны заранее. А это, зачастую, неоправданно ограничивает программиста. Например, вместо массива указателей на полиморфные объекты — получаем кортеж разнотипных объектов (по указателю или по значению — не суть важно).

Естественно, что оптимум — это использовать и то, и другое вместе.

Кстати говоря. Когда рассматриваешь рантайм-полиморфизм, не надо ограничивать себя "жёсткими" реализациями — виртуальными функциями. Есть ещё способы добиться похожих результатов — например, указатели на функции.
Так, шаблон boost::function для каждого случая заводит указатель на функцию-манипулятор, которую получает из шаблона функции. А Loki::Functor — объект класса-манипулятора по шаблону.
В результате у boost получается непрозрачный, трудно отлаживаемый, но достаточно компактный код. А у Loki — туча классов, что что ведёт к разбуханию RTTI.
Перекуём баги на фичи!
Re[2]: Compile-time vs. Runtime полиморфизм
От: GlebZ Россия  
Дата: 20.10.04 14:43
Оценка:
Здравствуйте, Кодт, Вы писали:


К>run-time-полиморфизм требует

К>* затрат на его поддержку (память под vtbl, vptr или аналогичные рукоделия; время на косвенный вызов; косвенный доступ к данным)
При правильном подходе, все можно испортить.
1. При compile-time генерация большого числа классов и соответсвенно расходы памяти CODE.
2. При compile-time доступ имеется только к открытому интерфейсу, соответсвенно невозможность работы с внутренними функциями и соответсвенно может пострадать время выполнения. К тому же тип сам по себе может быть виртуальным.
Так что все это относительно

К>Естественно, что оптимум — это использовать и то, и другое вместе.

Истина.

С уважением, Gleb.
Re[2]: Compile-time vs. Runtime полиморфизм
От: VladD2 Российская Империя www.nemerle.org
Дата: 20.10.04 17:57
Оценка:
Здравствуйте, Кодт, Вы писали:

Более корректно говорить о динамическом полиморфизме и о статическом полиморфизме.
Тогда все становится просто и ясно. Динамический требует затрат времени на проверки. Статический требует все проверки осуществить во время компиляции.

К>run-time-полиморфизм требует

К>* затрат на его поддержку (память под vtbl, vptr или аналогичные рукоделия; время на косвенный вызов; косвенный доступ к данным)
К>* бОльшей строгости интерфейсов (поскольку структура vtbl прибита гвоздями)

Втбл — это одна из реализаций. Вместо ВТБЛ можно с успехом использовать if-ы или switch-и.

К>Чистый compile-time полиморфизм, в свою очередь, требует, чтобы типы были известны заранее.


Тут неопределено понятие "известны заранее". Если заранее означает до реализации полиморфного класса/алгоритма, то утвреждение не верно. Если заранее означает до кмпиляции в непосредственный исполняемый код, то верно. Так те же шаблоны можно использовать с типами созданными позже чем шаблоны. Так же код может быть преобразован в некий промежуточный вариант (вроде МСИЛ-а или байт-кода) который будет поддерживать полиморфизм превращая таким образом динамический полиморфизм в статический.

К> А это, зачастую, неоправданно ограничивает программиста. Например, вместо массива указателей на полиморфные объекты — получаем кортеж разнотипных объектов (по указателю или по значению — не суть важно).


Проблема так же решается применением разных техник. Например, аля Variant в VB или any в корбе.

К>Естественно, что оптимум — это использовать и то, и другое вместе.


На самом деле оптимальным решением было бы переложить решение о применение некоторого метода на компилятор. По хорошему бы программист должен выражать намерение, а компилятор реализовывать его оптимальным образом (учитывая все нюансы). К сожалению современные языки и компиляторы редко задумываются об оптимальности и удобстве одновременно.

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

Думаю когда нибудь все прийдет к этому. А пока все это только теория.

К>Кстати говоря. Когда рассматриваешь рантайм-полиморфизм, не надо ограничивать себя "жёсткими" реализациями — виртуальными функциями. Есть ещё способы добиться похожих результатов — например, указатели на функции.


Таких способов много.

К>Так, шаблон boost::function для каждого случая заводит указатель на функцию-манипулятор, которую получает из шаблона функции. А Loki::Functor — объект класса-манипулятора по шаблону.

К>В результате у boost получается непрозрачный, трудно отлаживаемый, но достаточно компактный код. А у Loki — туча классов, что что ведёт к разбуханию RTTI.

Ну, разбугание и туча классов — это из-за того что средство не встроено в язык, а эмулируется подручными средсвами совсем для этого не предназначеными.

Намного стрешнее проблема которую я описал выше. Ведь Loki::Functor и boost::function решают — это аналоги фанкторов в ФЯ и делегатов в дотнете. А это суть разные реализации одной и той же абстракции. И оптимально было бы отложить выбор реализации до того момента когда будет четко ясно какя из них более приемлема. А так же снять брямя выбора с плеч программиста.
... << RSDN@Home 1.1.4 beta 3 rev. 206>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: Compile-time vs. Runtime полиморфизм
От: VladD2 Российская Империя www.nemerle.org
Дата: 20.10.04 23:36
Оценка: 4 (1)
Здравствуйте, Курилка, Вы писали:

К>Не знаешь, а есть где-нибудь строгое определение полиморфизма как такогого, ну и рассмотрение разн. вариантов было бы также интересно


По-моему, Википедское определение самое полное и достойное: http://en.wikipedia.org/wiki/Object-oriented_programming
... << RSDN@Home 1.1.4 beta 3 rev. 206>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: Compile-time vs. Runtime полиморфизм
От: Кодт Россия  
Дата: 21.10.04 07:58
Оценка:
Здравствуйте, VladD2, Вы писали:

К>>run-time-полиморфизм требует

К>>* затрат на его поддержку (память под vtbl, vptr или аналогичные рукоделия; время на косвенный вызов; косвенный доступ к данным)
К>>* бОльшей строгости интерфейсов (поскольку структура vtbl прибита гвоздями)

VD>Втбл — это одна из реализаций. Вместо ВТБЛ можно с успехом использовать if-ы или switch-и.


... и брать/вычислять тэг из данных объекта.

К>>Чистый compile-time полиморфизм, в свою очередь, требует, чтобы типы были известны заранее.


VD>Тут неопределено понятие "известны заранее". Если заранее означает до реализации полиморфного класса/алгоритма, то утвреждение не верно. Если заранее означает до кмпиляции в непосредственный исполняемый код, то верно. Так те же шаблоны можно использовать с типами созданными позже чем шаблоны. Так же код может быть преобразован в некий промежуточный вариант (вроде МСИЛ-а или байт-кода) который будет поддерживать полиморфизм превращая таким образом динамический полиморфизм в статический.


К>> А это, зачастую, неоправданно ограничивает программиста. Например, вместо массива указателей на полиморфные объекты — получаем кортеж разнотипных объектов (по указателю или по значению — не суть важно).


VD>Проблема так же решается применением разных техник. Например, аля Variant в VB или any в корбе.


Это всё тот же динамический полиморфизм. Где-то будет switch(vtType)...

<>

Про всё остальное —
Перекуём баги на фичи!
Re[4]: Compile-time vs. Runtime полиморфизм
От: VladD2 Российская Империя www.nemerle.org
Дата: 21.10.04 19:03
Оценка:
Здравствуйте, Кодт, Вы писали:

К>... и брать/вычислять тэг из данных объекта.


Естественно. Какая же динамика без изменяющихся данных?

К>Это всё тот же динамический полиморфизм. Где-то будет switch(vtType)...


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

Просто забавно слышать что код типа if (a) ... не требует поддержки в рантайме. А a.b() требует, так как b виртуальная функция.
... << RSDN@Home 1.1.4 beta 3 rev. 206>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: Compile-time vs. Runtime полиморфизм
От: prVovik Россия  
Дата: 21.10.04 20:18
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Втбл — это одна из реализаций. Вместо ВТБЛ можно с успехом использовать if-ы или switch-и.

В общем случае это не так. Для использования if или switch компилятору необходимо знать во время компиляции модуля обо ВСЕХ потомках обрабатываемого базового класса. Это требование, как правило, несовместимо с реальной жизнью
Короче, if/switch далеко не эквивалентны vtbl'у.
... << RSDN@Home 1.1.4 @@subversion >>
лэт ми спик фром май харт
Re[4]: Compile-time vs. Runtime полиморфизм
От: prVovik Россия  
Дата: 21.10.04 20:31
Оценка:
Здравствуйте, prVovik, Вы писали:

V>Это требование, как правило, несовместимо с реальной жизнью

Дабавлю, что:
1) Например, в С++ это требование выльется в то, чтобы всё находилось в одной единице трансляции ( т.е. в одном cpp файле ) — итого, БРЕД!
2) В .NET выльется в то, чтобы всё находилось в одной сборке — итого, БРЕД!

Вот ты говоришь "с успехом использовать". Не мог бы ты пояснить, где именно это можно с успехом использовать?
... << RSDN@Home 1.1.4 @@subversion >>
лэт ми спик фром май харт
Re[5]: Compile-time vs. Runtime полиморфизм
От: VladD2 Российская Империя www.nemerle.org
Дата: 21.10.04 21:53
Оценка: :)
Здравствуйте, prVovik, Вы писали:

V>Вот ты говоришь "с успехом использовать". Не мог бы ты пояснить, где именно это можно с успехом использовать?


Везде.
... << RSDN@Home 1.1.4 beta 3 rev. 206>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[5]: Compile-time vs. Runtime полиморфизм
От: Кодт Россия  
Дата: 22.10.04 07:55
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Я и не спорю. Я о том, что реализация может быть не одна. А динамика от статики и отличается только тем, что в рантайме анализируеются какие-то данные.


VD>Просто забавно слышать что код типа if (a) ... не требует поддержки в рантайме. А a.b() требует, так как b виртуальная функция.


if запросто может не требовать. Если значение условия выводится из типа...
Перекуём баги на фичи!
Re[6]: Compile-time vs. Runtime полиморфизм
От: VladD2 Российская Империя www.nemerle.org
Дата: 22.10.04 14:56
Оценка:
Здравствуйте, Кодт, Вы писали:

К>if запросто может не требовать. Если значение условия выводится из типа...


Их сам по себе выполняется в рантайме. Что при вызове виртуального метода, что при выполнении if-а производятся некие действия в рантайме. При этом никаких рантам-прдсистем не требуется. Это всего лишь код сгенерированный компилятором. Вот о чем я говорю.
... << RSDN@Home 1.1.4 beta 3 rev. 206>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.