Сообщение Re[16]: Concept-Based Polymorphism от 19.07.2020 6:30
Изменено 19.07.2020 6:44 so5team
Re[16]: Concept-Based Polymorphism
Здравствуйте, B0FEE664
Разговор, который начинался для выяснения того, что вы понимаете под "параметрическим полиморфизимом" начинает перерастать в спор о том, чьи определения полиморфизма должны считаться правильными. По ряду причин у меня нет ни возможности, ни желания развивать этот спор. Поэтому предлагаю закончить, т.к. я выяснил то, что мне было нужно.
Но, т.к. моя точка зрения могла остаться недопонятой, то тезисно по основным пунктам.
От классификации зависит понимание предмета собеседниками. Если у каждого из нас собственное представление о "параметрическом полиморфизме", то когда вы говорите "у меня в коде используется параметрический полиморфизм", то я ваши слова буду воспринимать совершенно не так. И наоборот.
Динамический полиморфизм в С и в C++ приниципально один и тот же. Различия лишь в том, что в C поддержка динамического полиморфизма полностью лежит на программисте, тогда как C++ предоставляет языковые средства для нее.
Типов полиморфизма, с которыми мне доводилось иметь дело, три:
Ad-hoc полиморфизм. В C++ реализуется как перегрузка:
Параметрический полиморфизм. В C++ реализуется в виде шаблонов:
Динамический и subtyping полиморфизм. В C++ реализуется из коробки через наследование с виртуальными методами. Либо же может быть реализован вручную на указателях на функции или std::function. Но традиционно понимается как наследование с виртуальными методами.
При этом в C++ термин "статический полиморфизм" является синонимом "параметрическому полиморфизму". Просто так сложилось. Поскольку перегрузка функций в C++ была с самого начала, еще до того, как термин "полиморфизм" вообще пришел в массы и в мире C++ перегрузку функций как полиморфизм рассматривают далеко не все C++ программисты.
Не трудно заметить, что и Ad-hoc, и параметрический полиморфизмы разрешаются в compile-time. Поэтому они оба могут называться "статическим полиморфизмом". Из-за чего сам по себе термин "статический полиморфизм" (в отрыве от C++ где у него исторически один смысл) не точный, за ним могут скрываться принципиально разные вещи.
То, что в случае с параметрическим полиморфизмом компилятор может сгенерировать разный код для разных типов параметров с точки зрения разновидностей полиморфизма роли не играет. Т.е. разработчик имеет дело только с исходным кодом, который оказывается один вне зависимости от типа параметров.
Сигнатура функции определяет тип функции. Поэтому, если у вас есть void(*)(), то уже без разницы, указатель на какие именно функции вы будете туда помещать. Поскольку вот это:
ничем не отличается вот от этого:
Поскольку оба фрагмента завязаны на конкретные типы: в первом случае на void(), во втором на int. Но типы зафиксированы, а то, что у экземпляров этих типов разные значения, то это обычное дело.
Параметрический полиморфизм бы здесь появился если бы consume научился бы брать разные типы. В случае с функциями consume должен бы был воспринимать не только void(), но и, скажем, int() или void(char*).
Детали реализации механизма слотов не важны по той же самой причине, по которой в математике не важно считаете ли вы количество яблок, количество палочек на парте или количество черточек, нарисованных на доске. Важно лишь то, что 2+2=4, вне зависимости от того, количество чего обозначено числами "2". Разница на первых этапах обучения существует только у детей, для которых подсчитывание палочек на парте и черточек на доске может выглядеть принципиально разными занятиями. Но по мере обучения развивается абстрактное мышление и эта разница исчезает.
Поэтому принципальное значение с точки зрения архитектуры является применение абстракции "слот". Детали же реализации "слота" на архитектуру влияния не оказывают, т.к. эти детали рассматриваются несколькими уровнями ниже.
Разговор, который начинался для выяснения того, что вы понимаете под "параметрическим полиморфизимом" начинает перерастать в спор о том, чьи определения полиморфизма должны считаться правильными. По ряду причин у меня нет ни возможности, ни желания развивать этот спор. Поэтому предлагаю закончить, т.к. я выяснил то, что мне было нужно.
Но, т.к. моя точка зрения могла остаться недопонятой, то тезисно по основным пунктам.
От классификации зависит понимание предмета собеседниками. Если у каждого из нас собственное представление о "параметрическом полиморфизме", то когда вы говорите "у меня в коде используется параметрический полиморфизм", то я ваши слова буду воспринимать совершенно не так. И наоборот.
Динамический полиморфизм в С и в C++ приниципально один и тот же. Различия лишь в том, что в C поддержка динамического полиморфизма полностью лежит на программисте, тогда как C++ предоставляет языковые средства для нее.
Типов полиморфизма, с которыми мне доводилось иметь дело, три:
Ad-hoc полиморфизм. В C++ реализуется как перегрузка:
bool equal(const char * a, const char * b);
bool equal(const std::string & a, const std::string & b);
bool equal(int a, int b);
bool equal(float a, float b);
Параметрический полиморфизм. В C++ реализуется в виде шаблонов:
template<typename T> bool equal(const T & a, const T & b) {...}
template<typename T> T min(T a, T b) {...}
Динамический и subtyping полиморфизм. В C++ реализуется из коробки через наследование с виртуальными методами. Либо же может быть реализован вручную на указателях на функции или std::function. Но традиционно понимается как наследование с виртуальными методами.
При этом в C++ термин "статический полиморфизм" является синонимом "параметрическому полиморфизму". Просто так сложилось. Поскольку перегрузка функций в C++ была с самого начала, еще до того, как термин "полиморфизм" вообще пришел в массы и в мире C++ перегрузку функций как полиморфизм рассматривают далеко не все C++ программисты.
Не трудно заметить, что и Ad-hoc, и параметрический полиморфизмы разрешаются в compile-time. Поэтому они оба могут называться "статическим полиморфизмом". Из-за чего сам по себе термин "статический полиморфизм" (в отрыве от C++ где у него исторически один смысл) не точный, за ним могут скрываться принципиально разные вещи.
То, что в случае с параметрическим полиморфизмом компилятор может сгенерировать разный код для разных типов параметров с точки зрения разновидностей полиморфизма роли не играет. Т.е. разработчик имеет дело только с исходным кодом, который оказывается один вне зависимости от типа параметров.
Сигнатура функции определяет тип функции. Поэтому, если у вас есть void(*)(), то уже без разницы, указатель на какие именно функции вы будете туда помещать. Поскольку вот это:
void say_hello() {...}
void format_disk() {...}
using pfn = void (*)();
void consume(pfn fn);
pfn a = say_hello;
pfn b = format_disk;
consume(a);
consume(b);
ничем не отличается вот от этого:
void consume(int v);
int a = 1234/45 + 56;
int b = 56 - 345/7 + 12*9;
consume(a);
consume(b);
Поскольку оба фрагмента завязаны на конкретные типы: в первом случае на void(), во втором на int. Но типы зафиксированы, а то, что у экземпляров этих типов разные значения, то это обычное дело.
Параметрический полиморфизм бы здесь появился если бы consume научился бы брать разные типы. В случае с функциями consume должен бы был воспринимать не только void(), но и, скажем, int() или void(char*).
Детали реализации механизма слотов не важны по той же самой причине, по которой в математике не важно считаете ли вы количество яблок, количество палочек на парте или количество черточек, нарисованных на доске. Важно лишь то, что 2+2=4, вне зависимости от того, количество чего обозначено числами "2". Разница на первых этапах обучения существует только у детей, для которых подсчитывание палочек на парте и черточек на доске может выглядеть принципиально разными занятиями. Но по мере обучения развивается абстрактное мышление и эта разница исчезает.
Поэтому принципальное значение с точки зрения архитектуры является применение абстракции "слот". Детали же реализации "слота" на архитектуру влияния не оказывают, т.к. эти детали рассматриваются несколькими уровнями ниже.
Re[16]: Concept-Based Polymorphism
Здравствуйте, B0FEE664
Разговор, который начинался для выяснения того, что вы понимаете под "параметрическим полиморфизимом" начинает перерастать в спор о том, чьи определения полиморфизма должны считаться правильными. По ряду причин у меня нет ни возможности, ни желания развивать этот спор. Поэтому предлагаю закончить, т.к. я выяснил то, что мне было нужно.
Но, т.к. моя точка зрения могла остаться недопонятой, то тезисно по основным пунктам.
От классификации зависит понимание предмета собеседниками. Если у каждого из нас собственное представление о "параметрическом полиморфизме", то когда вы говорите "у меня в коде используется параметрический полиморфизм", то я ваши слова буду воспринимать совершенно не так. И наоборот.
Динамический полиморфизм в С и в C++ приниципально один и тот же. Различия лишь в том, что в C поддержка динамического полиморфизма полностью лежит на программисте, тогда как C++ предоставляет языковые средства для нее.
Типов полиморфизма, с которыми мне доводилось иметь дело, три:
Ad-hoc полиморфизм. В C++ реализуется как перегрузка:
Параметрический полиморфизм. В C++ реализуется в виде шаблонов:
Динамический или subtyping полиморфизм. В C++ реализуется из коробки через наследование с виртуальными методами. Либо же может быть реализован вручную на указателях на функции или std::function. Но традиционно понимается как наследование с виртуальными методами.
При этом в C++ термин "статический полиморфизм" является синонимом "параметрическому полиморфизму". Просто так сложилось. Поскольку перегрузка функций в C++ была с самого начала, еще до того, как термин "полиморфизм" вообще пришел в массы и в мире C++ перегрузку функций как полиморфизм рассматривают далеко не все C++ программисты.
Не трудно заметить, что и Ad-hoc, и параметрический полиморфизмы разрешаются в compile-time. Поэтому они оба могут называться "статическим полиморфизмом". Из-за чего сам по себе термин "статический полиморфизм" (в отрыве от C++ где у него исторически один смысл) не точный, за ним могут скрываться принципиально разные вещи.
То, что в случае с параметрическим полиморфизмом компилятор может сгенерировать разный код для разных типов параметров с точки зрения разновидностей полиморфизма роли не играет. Т.е. разработчик имеет дело только с исходным кодом, который оказывается один вне зависимости от типа параметров.
Сигнатура функции определяет тип функции. Поэтому, если у вас есть void(*)(), то уже без разницы, указатель на какие именно функции вы будете туда помещать. Поскольку вот это:
ничем не отличается вот от этого:
Поскольку оба фрагмента завязаны на конкретные типы: в первом случае на void(), во втором на int. Но типы зафиксированы, а то, что у экземпляров этих типов разные значения, то это обычное дело.
Параметрический полиморфизм бы здесь появился если бы consume научился бы брать разные типы. В случае с функциями consume должен бы был воспринимать не только void(), но и, скажем, int() или void(char*).
Детали реализации механизма слотов не важны по той же самой причине, по которой в математике не важно считаете ли вы количество яблок, количество палочек на парте или количество черточек, нарисованных на доске. Важно лишь то, что 2+2=4, вне зависимости от того, количество чего обозначено числами "2". Разница на первых этапах обучения существует только у детей, для которых подсчитывание палочек на парте и черточек на доске может выглядеть принципиально разными занятиями. Но по мере обучения развивается абстрактное мышление и эта разница исчезает.
Поэтому принципальное значение с точки зрения архитектуры является применение абстракции "слот". Детали же реализации "слота" на архитектуру влияния не оказывают, т.к. эти детали рассматриваются несколькими уровнями ниже.
Разговор, который начинался для выяснения того, что вы понимаете под "параметрическим полиморфизимом" начинает перерастать в спор о том, чьи определения полиморфизма должны считаться правильными. По ряду причин у меня нет ни возможности, ни желания развивать этот спор. Поэтому предлагаю закончить, т.к. я выяснил то, что мне было нужно.
Но, т.к. моя точка зрения могла остаться недопонятой, то тезисно по основным пунктам.
От классификации зависит понимание предмета собеседниками. Если у каждого из нас собственное представление о "параметрическом полиморфизме", то когда вы говорите "у меня в коде используется параметрический полиморфизм", то я ваши слова буду воспринимать совершенно не так. И наоборот.
Динамический полиморфизм в С и в C++ приниципально один и тот же. Различия лишь в том, что в C поддержка динамического полиморфизма полностью лежит на программисте, тогда как C++ предоставляет языковые средства для нее.
Типов полиморфизма, с которыми мне доводилось иметь дело, три:
Ad-hoc полиморфизм. В C++ реализуется как перегрузка:
bool equal(const char * a, const char * b);
bool equal(const std::string & a, const std::string & b);
bool equal(int a, int b);
bool equal(float a, float b);
Параметрический полиморфизм. В C++ реализуется в виде шаблонов:
template<typename T> bool equal(const T & a, const T & b) {...}
template<typename T> T min(T a, T b) {...}
Динамический или subtyping полиморфизм. В C++ реализуется из коробки через наследование с виртуальными методами. Либо же может быть реализован вручную на указателях на функции или std::function. Но традиционно понимается как наследование с виртуальными методами.
При этом в C++ термин "статический полиморфизм" является синонимом "параметрическому полиморфизму". Просто так сложилось. Поскольку перегрузка функций в C++ была с самого начала, еще до того, как термин "полиморфизм" вообще пришел в массы и в мире C++ перегрузку функций как полиморфизм рассматривают далеко не все C++ программисты.
Не трудно заметить, что и Ad-hoc, и параметрический полиморфизмы разрешаются в compile-time. Поэтому они оба могут называться "статическим полиморфизмом". Из-за чего сам по себе термин "статический полиморфизм" (в отрыве от C++ где у него исторически один смысл) не точный, за ним могут скрываться принципиально разные вещи.
То, что в случае с параметрическим полиморфизмом компилятор может сгенерировать разный код для разных типов параметров с точки зрения разновидностей полиморфизма роли не играет. Т.е. разработчик имеет дело только с исходным кодом, который оказывается один вне зависимости от типа параметров.
Сигнатура функции определяет тип функции. Поэтому, если у вас есть void(*)(), то уже без разницы, указатель на какие именно функции вы будете туда помещать. Поскольку вот это:
void say_hello() {...}
void format_disk() {...}
using pfn = void (*)();
void consume(pfn fn);
pfn a = say_hello;
pfn b = format_disk;
consume(a);
consume(b);
ничем не отличается вот от этого:
void consume(int v);
int a = 1234/45 + 56;
int b = 56 - 345/7 + 12*9;
consume(a);
consume(b);
Поскольку оба фрагмента завязаны на конкретные типы: в первом случае на void(), во втором на int. Но типы зафиксированы, а то, что у экземпляров этих типов разные значения, то это обычное дело.
Параметрический полиморфизм бы здесь появился если бы consume научился бы брать разные типы. В случае с функциями consume должен бы был воспринимать не только void(), но и, скажем, int() или void(char*).
Детали реализации механизма слотов не важны по той же самой причине, по которой в математике не важно считаете ли вы количество яблок, количество палочек на парте или количество черточек, нарисованных на доске. Важно лишь то, что 2+2=4, вне зависимости от того, количество чего обозначено числами "2". Разница на первых этапах обучения существует только у детей, для которых подсчитывание палочек на парте и черточек на доске может выглядеть принципиально разными занятиями. Но по мере обучения развивается абстрактное мышление и эта разница исчезает.
Поэтому принципальное значение с точки зрения архитектуры является применение абстракции "слот". Детали же реализации "слота" на архитектуру влияния не оказывают, т.к. эти детали рассматриваются несколькими уровнями ниже.