Здравствуйте, so5team, Вы писали:
S>Разговор, который начинался для выяснения того, что вы понимаете под "параметрическим полиморфизимом" начинает перерастать в спор о том, чьи определения полиморфизма должны считаться правильными. По ряду причин у меня нет ни возможности, ни желания развивать этот спор. Поэтому предлагаю закончить, т.к. я выяснил то, что мне было нужно.
Ну, хорошо, что вы выяснили то, что вам было нужно, я правда так и не понял, что именно. Замечу ещё, что с самого начала я пытался дважды уклониться от выяснения определений, так как знал, что это бессмысленное занятие.
S>От классификации зависит понимание предмета собеседниками. Если у каждого из нас собственное представление о "параметрическом полиморфизме", то когда вы говорите "у меня в коде используется параметрический полиморфизм", то я ваши слова буду воспринимать совершенно не так. И наоборот.
Именно поэтому я привёл код, который всё проясняет и работает не зависимо от того, что и как называть.
S>Динамический полиморфизм в С и в C++ приниципально один и тот же. Различия лишь в том, что в C поддержка динамического полиморфизма полностью лежит на программисте, тогда как C++ предоставляет языковые средства для нее.
S>Типов полиморфизма, с которыми мне доводилось иметь дело, три:
S>Ad-hoc полиморфизм. В C++ реализуется как перегрузка:
S>S>bool equal(const char * a, const char * b);
S>bool equal(const std::string & a, const std::string & b);
S>bool equal(int a, int b);
S>bool equal(float a, float b);
S>
S>Параметрический полиморфизм. В C++ реализуется в виде шаблонов:
S>S>template<typename T> bool equal(const T & a, const T & b) {...}
S>template<typename T> T min(T a, T b) {...}
S>
S>Динамический или subtyping полиморфизм. В C++ реализуется из коробки через наследование с виртуальными методами. Либо же может быть реализован вручную на указателях на функции или std::function. Но традиционно понимается как наследование с виртуальными методами.
Есть ещё один вид, самый первый, который используется, например, в qsort. qsort — общий код для неважно каких типов сортируемых массивов.
| Скрытый текст |
| struct segment { int start; int end; };
int seg_cmpr( struct segment *a, struct segment *b )
{ return abs( a->end - a->start ) - abs( b->end - b->start ); }
int str_cmpr( char **a, char **b )
{ return strcmp( *a, *b ); }
struct segment segs[] = { {2,5}, {4,3}, {9,3}, {6,8} };
char* strs[] = { "three", "one", "two", "five", "four" };
main()
{
qsort( strs, sizeof(strs)/sizeof(char*), sizeof(char*),
(int (*)(void*,void*))str_cmpr );
qsort( segs, sizeof(segs)/sizeof(struct segment), sizeof(struct segment),
(int (*)(void*,void*))seg_cmpr );
...
}
|
| |
S>При этом в C++ термин "статический полиморфизм" является синонимом "параметрическому полиморфизму". Просто так сложилось. Поскольку перегрузка функций в C++ была с самого начала, еще до того, как термин "полиморфизм" вообще пришел в массы и в мире C++ перегрузку функций как полиморфизм рассматривают далеко не все C++ программисты.
Я знаю про общее правило: если что-то в классификации обусловлено историческими причинами, aka "так сложилось", то значит в классификации есть проблемы. Такой эффект можно наблюдать в любой области: от классификации плодов растений (фрукт/овощ/ягода ...), до классификации планет в астрономии.
А вообще интересно: вот если в C++ добавить шаблонный виртуальный метод (что не сложно сделать вручную), то какой тип будет у такого полиморфизма в вашей классификации?
S>Детали реализации механизма слотов не важны по той же самой причине, по которой в математике не важно считаете ли вы количество яблок, количество палочек на парте или количество черточек, нарисованных на доске. Важно лишь то, что 2+2=4, вне зависимости от того, количество чего обозначено числами "2". Разница на первых этапах обучения существует только у детей, для которых подсчитывание палочек на парте и черточек на доске может выглядеть принципиально разными занятиями. Но по мере обучения развивается абстрактное мышление и эта разница исчезает.
В том-то и дело, что для для программистов, в отличии от математиков, разница в конкретном и абстрактном есть. Возьмём сумму 2 + 2 + 2 + 2, математику не важно сколько операций сложения в этом выражении, а программист должен уметь получать результат такого выражения за (максимум) две операции сложения.
S>Поэтому принципальное значение с точки зрения архитектуры является применение абстракции "слот". Детали же реализации "слота" на архитектуру влияния не оказывают, т.к. эти детали рассматриваются несколькими уровнями ниже.
Ну так я вам об этом же и писал:
BFE>std::function<void()> — это абстрактный символ, который может представлять любой тип. Согласны?
Нет. Это конкретный тип, который обозначает функцию без аргументов, возвращающую void. И ваше решение завязано конкретно на этот тип.
std::function<void()> — это слот и его реализация не важна. Так что я опять не понимаю, о чём вы толкуете.
Впрочем для меня это не важно, важно другое: использование слотов вместо виртуальных функций меняет подходы к задачам и их решение. В частности, задачу исходного сообщения (так, которая на хабре), технология signal-slot решит довольно просто. Важно это, а не то как в этот году называется тот или иной полиморфизм.