На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Модераторы: Qraizer, Hsilgos
  
> О шаблонах
    А правда ли что тема "шаблоны" - это совершенно отдельная тема и знание СИ и даже С++ без шаблонов тут мало поможет?
    Что это ближе к математике, где также идет манипулирование значками и символами.

    И какая книга ЛУЧШАЯ по шаблонам в С++.
    ЛУЧШАЯ. ИМЕННО по шаблонам, а не по С++ вообще

    И давайте обсудим зачем они вообще нужны по большому-то счету.
    Чиста для обобщения (парадигма "обобщенное программирование") и сокращения объёма писанины?

    А правда ли, что шаблоны - это те же макросы к которым добавили различные проверки?

    Эта тема была разделена из темы "А правда "шаблоны" - это совершенно отдельная тема в программировании на С++?"
      Цитата Исмаил Прокопенко @
      А правда ли что тема "шаблоны" - это совершенно отдельная тема...


      Нет. Но почти отдельная.

      Современный C++, но без шаблонов, это почти тот же C++ который был 30 лет назад. Или даже 40.
      Так вышло, что они сейчас почти везде в стандартной библиотеке.
      Даже когда новичок пишет свою первую программу, он неосознанно использует шаблоны.
      объект cout это экземпляр класса ostream, который сделан из шаблона класса basic_istream.

      Цитата Исмаил Прокопенко @
      и знание СИ и даже С++ без шаблонов тут мало поможет?


      Угу. Мало. Только вот тому кто не знает C++, шаблоны нафиг не нужны. Ибо шаблоны это вспомогательный инструмент.

      Цитата Исмаил Прокопенко @
      Что это ближе к математике, где также идет манипулирование значками и символами.


      На вкус и на цвет... Там свои, немного иные выверты. Но манипулирование или даже жонглирование надо прокачивать.

      Цитата Исмаил Прокопенко @
      И какая книга ЛУЧШАЯ по шаблонам в С++. ЛУЧШАЯ. ИМЕННО по шаблонам, а не по С++ вообще


      Во-первых, без знания C++ в шаблоны лезть нет смысла. Ибо новичку особо не нужно. Нет цели для применения шаблонов на базовом уровне. Даже игры не интересные.

      Во-вторых, в процессе изучения C++, понимание и необходимость применение шаблонов придёт. Поскольку сам язык и особенно его стандартная библиотека завязана на шаблонах.

      В-третьих, сейчас область применения шаблонов, всё ещё расширяется. Продолжают придумывать новые трюки. Продолжают переделывать язык и компилятор. И актуальность старых книг постепенно снижается. Был когда-то auto_ptr, но его запретили, заменив unique_ptr.

      В своё время, мне советовали:
      "Шаблоны C++: справочник разработчика"
      Автор: Дэвид Вандевурд, Николай М. Джосаттис.
      Но с той поры, слишком много воды утекло.

      Цитата Исмаил Прокопенко @
      зачем они вообще нужны по большому-то счету.
      Чиста для обобщения (парадигма "обобщенное программирование") и сокращения объёма писанины?


      Да. Именно для сокращения писанины.

      Можно например разработать шаблон класса хранящий умный указатель на объект. А потом использовать этот шаблон, для умных указателей на объекты разных типов.
      см unique_ptr, shared_ptr, weak_ptr.

      Можно например разработать шаблон класса управления коллекции объектов. А потом использовать этот шаблон для коллекций объектов разных типов.
      см vector, list, array и т.д.

      Это как бы база, с которой шаблоны начинались.

      Сейчас шаблоны вообще могут произвести вычисления, прямо на этапе компиляции.

      Цитата Исмаил Прокопенко @
      А правда ли, что шаблоны - это те же макросы к которым добавили различные проверки?


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

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

      Например, использоя шаблоны, можно в compile-time получить информацию о произвольном типе. Можно даже модифицировать этот тип.
      Причём, поскольку шаблоны, обрабатываются и разворачиваются при компиляции, то на скорости выполнения кода это не отражается. А если пошаманить, то даже ускоряется.
        Цитата Eric-S @
        В своё время, мне советовали:
        "Шаблоны C++: справочник разработчика"
        Автор: Дэвид Вандевурд, Николай М. Джосаттис.
        Но с той поры, слишком много воды утекло.

        Есть свежее издание: David Vandevoorde, C++ Templates: The Complete Guide (2nd Edition).
          Eric-S Скажите. А почему в качестве параметров шаблонов ограничились типами (в том числе параметрическими) и переменными?
          И почему ограничились "сосредоточенными" параметрами (т.е. когда подстановка фактических параметров происходит только в заранее заданные УЖЕ ИЗВЕСТНЫЕ точки, а не когда они "размазаны"/распределены по коду)?
          Почему нельзя было сделать более гибкие и интеллектуальные грамматики?
          Сообщение отредактировано: Исмаил Прокопенко -
            Цитата Исмаил Прокопенко @
            А почему в качестве параметров шаблонов ограничились типами (в том числе параметрическими) и переменными?


            Возможно я ваш вопрос понял превратно.
            Вы наверное хотели спросить:

            q: почему в качестве параметров шаблонов используются только типы и переменные?

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

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

            Сейчас, это пересмотрели. Но немного с другой стороны.
            Если компилятор, может что-то сосчитать на этапе компиляции, то пусть считает.
            Но всё равно шаблоны не нужны в этом деле. Есть классический синтаксис оформления алгоритмов. Он подходит гораздо лучше.
            А чтоб компилятор знал, когда ему надо попытаться сделать расчёты, то добавили ключевое слово "constexpr".
            Помечайте им выражения и функции, которые удовлетворяют условиям и компилятор попытается их интерпретировать во время компиляции.

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

            Лично я бы ещё хотел добавить к ним токены или названия. Было бы прикольно. Хотя над этим надо хорошенько подумать. Возможно я придумал глупость.

            Цитата Исмаил Прокопенко @
            И почему ограничились "сосредоточенными" параметрами (т.е. когда подстановка фактических параметров происходит только в заранее заданные УЖЕ ИЗВЕСТНЫЕ точки, а не когда они "размазаны"/распределены по коду)?


            Этого вопроса почти не понял.
            В каком смысле "сосредоточенный параметр"?

            Впрочем, не вы первый, не вы последний.
            Видимо, как и прочие, вы хотели спросить:

            q: почему шаблон раскрывается и проверяется только в том месте, где ему передают уже конкретные параметры?

            a: Чтобы раскрыть шаблон заранее, незная какие в него передадут параметры, в компьютере категорически необходим модуль предсказания будущего, гадания по звёздам, на кофейной гуще или тому подобная эзотерическая хрень.
            Ну а поскольку компьютер не умеет предсказывать, он делает только то, что его просят.
            Это кстати прямо прописано в философии C++. Делать только то, что нужно, было явно запрошено и не умничать.
            Если вам не нравится такая философия, то посмотрите в сторону других языков, которые подтерают сопельки и даже мусор приберают за программистом. Но не дают ему сделать ни единого шага в сторону.

            На самом деле, причин так поступать, весьма много.
            У шаблонов бывает много хитростей, много тонкостей. И если использовать их особенности, то можно будет сотворить магию.
            Если же сразу прибивать гвоздями, то магия сломается и ничего уже не получится.

            Например, есть специализация шаблонных классов.

            Оно изначально задумывалось именно как специализация. Например если какой-то параметр особенный, то его надо обработать специальным способом, а не первоначальным.
            Пример можно глянуть в старом vector< bool >.
            То есть тот же вектор, почти всё тоже самое, но значение хранит в сжатом виде.

            Только вот специализированный шаблонный класс, это совсем другой класс! Он похож только названием. Всё остальное у него может быть совсем иным.

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

            Например в C# есть генерики. Очень ущербныйе недошаблоны.
            Они сразу проверяют базовый тип на корректность и полную совместимость. Если тип не удовлетворил строгим требованиям, то программа откажется компилироваться. Ибо шаг в сторону считается побегом и присекается растрелом на месте.

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

            Так вот, в чистом C++, который C с классами, полиморфизм только динамический.
            Это когда вы создаёте дочерний класс и переопределяете виртуальные методы.
            Он боле строг к программисту, автоматически проверяется на этапе компиляции. А во время исполнения программы, оплачивается косвенной адресацией при вызове виртуальных методов.

            В C++ с шаблонами, можно сделать статический полиморфизм.
            Это когда класс умозрительно наследует какой-то интерфейс. То есть просто имеет члены с такими же названиями.
            Статический полиморфизм проверяется частично, по правилам утки "если выглядит как утка, плавает как утка, крякает как утка, то это утка и есть".
            Оплачивается увеличением объёма машинного кода, но зато работает максимально быстро. Ведь там нет косвенной адресации, все вызовы прямые.

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

            Цитата Исмаил Прокопенко @
            Почему нельзя было сделать более гибкие и интеллектуальные грамматики?


            Это больной вопрос. Когда придумывали шаблоны C++, альтернатив не имелось. Первопроходцы шлип в тумане. Естественно ошибались.
            Впрочем, сейчас, когда есть альтернативы, то не могу сказать, что их синтаксис брызжет гениальностью.

            Шаблоны C++, пусть невзрачны, непривычны, на первый взгляд, но позволяют делать очень многое. А все чужие альтернативы им уступают по набору возможностей.

            Ничего, грозились в 2023 году добавить в стандарт ещё метаклассы. Судя по описанию, это будет нечто эпичное и шедевральное.

            В любом случае, каждому инструменту своя область применения.
              Eric-S
              А вот ещё такая хрень меня смущает.
              Пишуть часто, что вся прелесть шаблона класса в том, что как только ты его отладил, то ты можешь использовать его с ЛЮБЫМИ типами, передаваемыми как фактические параметры без переписывания кода. При этом чаще всего приводят пример шаблона "список", который может работать с элементами любого типа.

              Но это пример надуманный, синтетический.

              Можно придумать и другие примеры.

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

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

              Понятное дело, что речь идёт о сложных типах (классах).

              Поясню на простом примере

              ExpandedWrap disabled
                template <class subtype> class X {
                ...
                subtype Y;
                ...
                int metod(int a){
                ...
                   Y.go(7);
                ...
                }
                ...
                }


              Т.е. получается, что как параметры могут использоваться классы, имеющие метод go.
              Или по другому, когда пишешь тип, который будет использоваться в шаблоне X, ты должен предусмотреть метод go.

              Т.е. получаются трудно контролируемые и трудно прослеживаемые завязки, которые "сводят на нет" все якобы преимущества шаблонов :yes-sad:

              Добавлено
              Т.е. в сложных случая определить можешь ли ты данный тип передавать как параметр в шаблон не представляется возможным.

              И как тут быть тогда?

              Добавлено
              Т.е. на самом деле ты должен,получается, держать в голове какой-то абстрактный никак формально не описываемый в коде интерфейс шаблона, которому должны удовлетворять все классы, которые можно будет передавать как параметры в шаблон
              Сообщение отредактировано: Исмаил Прокопенко -
                Цитата Исмаил Прокопенко @
                Или по другому, когда пишешь тип, который будет использоваться в шаблоне X, ты должен предусмотреть метод go.
                Да, именно так.
                Но ничто не мешает тебе написать второй шаблон, который работает с классами, не имеющими метода go, и выполняющими нужные действия через другой доступный интерфейс. Тогда при попытке инстанцировать основной шаблон произойдёт ошибка и компилятор, обнаружив альтернативу, попробует инстанцировать второй шаблон. (Если не ошибаюсь, C++ позволяет описывать несколько шаблонов с идентичным заголовком, инстанцируя первый, подошедший по реализации).
                Или можешь написать шаблонный класс-посредник, реализующий нужный тебе go, и передавать в шаблон его. Можешь даже заставить компилятор автоматически создавать экземпляр-посредник, написав второй шаблон для классов не имеющих go.
                  Цитата amk @
                  Если не ошибаюсь, C++ позволяет описывать несколько шаблонов с идентичным заголовком, инстанцируя первый, подошедший по реализации
                  Ошибаешься. SFINAE не для этого. Но ты можешь написать шаблонный метакод, который научит компилятор этому поведению.
                    Цитата Исмаил Прокопенко @
                    А вот ещё такая хрень меня смущает.
                    Пишуть часто, что вся прелесть шаблона класса в том, что как только ты его отладил, то ты можешь использовать его с ЛЮБЫМИ типами, передаваемыми как фактические параметры без переписывания кода.


                    Верно. Если функционал устраивает, то зачем переписывать?

                    Цитата Исмаил Прокопенко @
                    При этом чаще всего приводят пример шаблона "список", который может работать с элементами любого типа.

                    Но это пример надуманный, синтетический.


                    Вполне практически пример. Правда этот список уже давно написали и юзают. То есть утверждение подкреплёное многолетней практикой.
                    Но это будет так же верно для любых других шаблонов.
                    Есть конечно оговорки из-за косвенных причин. Например изменится язык или обнаружится ошибка. Но это уже другой разговор.

                    Цитата Исмаил Прокопенко @
                    Когда шаблон, чтобы работать с типами, передаваемыми ему как параметры, должен знать "правила игры" и "внутреннюю кухню" этих типов.


                    Шаблону не нужно и даже нельзя знать внутреннюю кухню кого-либо.
                    Это вообще-то называется грубым хаком и категорически не приветствуется.
                    Достаточно знать внешний интерфейс типа.

                    Цитата Исмаил Прокопенко @
                    Или напротив, типы, которые ты собрался передавать в шаблон как параметры, должны знать "правила игры" шаблона, т.е. как они будут использоваться в шаблоне.


                    Опять же нет. Подумать конечно надо. но это всего лишь пожелания.
                    Например в std есть контейнеры. У них есть стандартные члены.
                    Можешь написать свой контейнер. Было бы хорошо, добавить к ним члены со стандартными названиями.
                    Например методы size(), begin(, end() и так далее.
                    Если соблюдать эти правила, то новому пользователю твоего контейнера, человеку или шаблону, сразу будет понятно, что и как с ним делать.

                    А если нарушать общие правила, то да, можно сделать адаптер или же его функциональный аналог.
                    Например у стандартного массива, нет методов begin() и end().
                    Зато существуют функции std::begin() и std::end() которые получив контейнер или стандартный массив, одинаково получат и вернут итераторы.

                    Цитата Исмаил Прокопенко @
                    Т.е. получается, что как параметры могут использоваться классы, имеющие метод go.
                    Или по другому, когда пишешь тип, который будет использоваться в шаблоне X, ты должен предусмотреть метод go.


                    Я выше уже писал про статический полиморфизм. Вот он во всей красе. А проблемы-то те же самые, что и с динамическим полиморфизмом. А решаются они, очень похожим способом.
                    Но это не проблема шаблонов. Это проблема архитектуры приложения или его отдельных решений.

                    Цитата Исмаил Прокопенко @
                    Т.е. получаются трудно контролируемые и трудно прослеживаемые завязки, которые "сводят на нет" все якобы преимущества шаблонов :yes-sad:


                    Повторю! Это не проблема шаблонов. У них другие фишки. Не надо решать шаблонами чужие проблемы.

                    Ах да. Если сделать шаблонную обёртку класса, то она будет работать быстрее, чем нешаблонная. Поскольку компилятор шаблоны раскрывает перед компиляцией.

                    Цитата Исмаил Прокопенко @
                    Т.е. в сложных случая определить можешь ли ты данный тип передавать как параметр в шаблон не представляется возможным.

                    И как тут быть тогда?


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

                    Обычно всё бывает очень просто и понятно. Хотя, некоторые базовые моменты, надо заучить.
                    Например, если тебе дают контейнер неизвестного типа, то для получения итераторов вызывай функции begin() и end()

                    ExpandedWrap disabled
                      template< typename T >
                      void foo( const T& contayner )
                        {
                        for( auto iter = begin( contayner ); end( contayner ) != iter; ++iter )
                          {
                          action( *iter );
                          }
                        }


                    Использовал старую форму for, для большей наглядности.
                    Не использовал foreach поскольку не знаю и не хочу знать типа элемента контейнера.

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

                    Цитата Исмаил Прокопенко @
                    Т.е. на самом деле ты должен,получается, держать в голове какой-то абстрактный никак формально не описываемый в коде интерфейс шаблона, которому должны удовлетворять все классы, которые можно будет передавать как параметры в шаблон


                    Зачастую, держать в голове весь интерфейс нафиг не нужно. Достаточно держать лишь ключевые момменты этого интерфейса. Ну и никто не мешает держать под рукой открытый справочник.

                    Ах да. Рекомендации для разработчиков шаблонных классов и функций.

                    1. будте проще, пишите код коротким и понятным. Если надо, то разделяйте. Божественные классы и функции это зло.

                    2. Изобретайте своё, только если нет стандартов, аналогов. Иначе не выёживайтесь и пользуйтесь чужими наработками.

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

                    4. Предполагайте, что ваш тип (класс, структура, объединение, шаблонный класс) будет обрабатыватся стандартными шаблонными функциями. Сделайте интерфейс вашего типа максимально стандартным или иметирующим стандартное поведение.
                      Цитата amk @
                      Цитата Исмаил Прокопенко @
                      Или по другому, когда пишешь тип, который будет использоваться в шаблоне X, ты должен предусмотреть метод go.
                      Да, именно так.
                      Но ничто не мешает тебе написать второй шаблон, который работает с классами, не имеющими метода go, и выполняющими нужные действия через другой доступный интерфейс. Тогда при попытке инстанцировать основной шаблон произойдёт ошибка и компилятор, обнаружив альтернативу, попробует инстанцировать второй шаблон. (Если не ошибаюсь, C++ позволяет описывать несколько шаблонов с идентичным заголовком, инстанцируя первый, подошедший по реализации).
                      Или можешь написать шаблонный класс-посредник, реализующий нужный тебе go, и передавать в шаблон его. Можешь даже заставить компилятор автоматически создавать экземпляр-посредник, написав второй шаблон для классов не имеющих go.

                      И это называется "упрощение жизни программисту"? :blink: :wall:

                      Да тут блин получается просто пастбище для не очевидных, трудно прослеживаемых багов >:(

                      Добавлено
                      Цитата Eric-S @
                      Если не понятно, смотрим реализацию

                      О том и речь. Мы, прежде чем передать тип как параметр, должны будем проштудировать весь гигантский код шаблона класса. :oops: :'(

                      Это называется "назло маме отморожу уши"

                      Добавлено
                      Цитата Qraizer @
                      Зачастую, держать в голове весь интерфейс нафиг не нужно. Достаточно держать лишь ключевые момменты этого интерфейса. Ну и никто не мешает держать под рукой открытый справочник.

                      Вот о том и речь.
                      "Гладко было на бумаге, а по факту вылезли буераки"©

                      Цитата
                      Достаточно держать лишь ключевые момменты этого интерфейса

                      Проблема в том, что он в коде никак явно, наглядно и сжато не выделяется.
                      Синтаксис С++ это не предусматривает.
                      Он как бы "размазан" по всему коду шаблона класса

                      Добавлено
                      Цитата amk @
                      будте проще, пишите код коротким и понятным.

                      О том и речь. Что шаблоны реально хороши только в простейших ("синтетических", специально придуманных для демонстрации преимуществ шаблонов) случаях. А если возьмёшь шаблон чуть посложней и тут начинается попа

                      Добавлено
                      Цитата Eric-S @
                      Предполагайте, что параметром вашего шаблона будет любой из стандартных типов

                      Вот вот.
                      Цитата Исмаил Прокопенко @
                      шаблоны реально хороши только в простейших ("синтетических", специально придуманных для демонстрации преимуществ шаблонов) случаях.


                      Таким образом механизм шаблонов очень ограничен и его можно безопасно юсать только с простейшими типами
                      Сообщение отредактировано: Исмаил Прокопенко -
                        Исмаил Прокопенко, мужики давным давно придумали концепты (про которые ты, в сущности, и пишешь). В C++20 они даже частью стандарта станут. А в остальном - все нормальные мужики давно и плотно используют программирование на шаблонах (либо его результаты). Остальные - толкуют про "синтетические примеры".
                          Исмаил Прокопенко, ваши реплики действительно напоминают троллинг. Но я всё же отвечу. Тема отдельная. А вы топикстартер. Так что можем похоливарить в рамках сабжа.
                          Но ваши вопросы стали нудными и скучными. Если так продолжится, то я поленюсь отвечать.
                          Мне не интересно отвечать на скучные вопросы.

                          Цитата Исмаил Прокопенко @
                          А если "мужики" (в Вашем лице) знают, то почему молчали? Почему СКРЫВАЛИ эти подлые факты от народа? А? :wall: >:(


                          В предыдущих комментах, я очень толсто намекнул на конкретные исторические причины. Но могу повторить.
                          Шаблоны придумывались для упрощения обработки простых типов, для упрощения создания новых типов.
                          Изначально шаблонам выделялась вполне конкретная и весьма узкая ниша.
                          Но они оказались гораздо мощнее, чем могли предположить создатели.
                          А область применения оказалась гораздо шире, чем кто либо мог вообразить.
                          А чо теперь жаловаться? Получили на халяву уникальный инструмент.
                          Ну да, он не идеален, со своими заморочками, зато халявный. Осталось лишь приложить мозг.
                          Вообщем так. Если вам шаблоны не нравяться, то идите в лес.
                          Не хотите жрать, что дают, так не жрите, вас не заставляют!

                          Цитата Исмаил Прокопенко @
                          И это называется "упрощение жизни программисту"? :blink: :wall:


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

                          В любом случае, это проблема архитектуры типов.
                          Шаблоны тут вообще не виноваты.

                          Знаете же проблему ценности?
                          Это когда есть крутая и дорогая вещь или же странная и дешевая?
                          И ваше право платить за то, что нравится.
                          Хотите строгий виртуальный интерфейс? Хорошо, делайте код руками, получайте тормоза при исполнении. Зато всё строго и компактно в машинном коде.
                          Хотите гибкость, быстрое написание, быстрое исполнение? Хорошо, но интерфейс придётся держать в голове.
                          В русских сказках описан камень на распутье, туда пойдёшь, то-то потеряешь... Вот и тут точно так же.

                          Цитата Исмаил Прокопенко @
                          Да тут блин получается просто пастбище для не очевидных, трудно прослеживаемых багов >:(


                          Как всегда. "Это C++ детка!"
                          Если хочешь отстрелить себе ногу, то дерзай!

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

                          Цитата Исмаил Прокопенко @
                          О том и речь. Мы, прежде чем передать тип как параметр, должны будем проштудировать весь гигантский код шаблона класса. :oops: :'(


                          Опять вы перепутали!

                          1. шаблоны отдельно, тип отдельно. В том смысле, если хотим передавать куда-то некий тип, то смотрим интерфейс этого типа. И тут нас не должно волновать шаблонный он или нет.

                          2. весь код перерывать тоже не нужно. Смотрим только интерфейс! А зачастую просто проверяем его соответствие ожидаемому интерфейсу.

                          Цитата Исмаил Прокопенко @
                          Это называется "назло маме отморожу уши"


                          Мне вот кажется, что ваши реплики подразумевают:
                          "не люблю манную кашу, ну что в ней хорошего?"

                          Ну в самом деле, как маленький.
                          "если вам не нравятся кошки, значит вы не умеете их готовить"

                          Цитата Исмаил Прокопенко @
                          Вот о том и речь.
                          "Гладко было на бумаге, а по факту вылезли буераки"


                          Если бы! Шаблоны вообще не предполагали использовать так широко, как их используют.
                          Это было узконишевое решение, для упрощения разработки классов стандартной библиотеки.
                          Всё! Шаблоны успешно исполнили возложенную задачу.


                          Цитата Исмаил Прокопенко @
                          Проблема в том, что он в коде никак явно, наглядно и сжато не выделяется.
                          Синтаксис С++ это не предусматривает.
                          Он как бы "размазан" по всему коду шаблона класса


                          Ой ли? Неужели? Шаблонный класс от обычного почти не отличается. Но обычный-то как то просматривают? А если очень трудно, то можно заюзать какую-нибудь тулзу. Например doxygen умеет описывать интерфейс классов.

                          Цитата Исмаил Прокопенко @
                          О том и речь. Что шаблоны реально хороши только в простейших ("синтетических", специально придуманных для демонстрации преимуществ шаблонов) случаях. А если возьмёшь шаблон чуть посложней и тут начинается попа


                          Шаблоны и предназначались для простейших случаев. Шаблоны нужно использовать для простейших случаев. Требовать от них чего-то большего... Вы же не пытаетесь выйти на орбиту, содясь за руль запорожца?

                          Цитата Исмаил Прокопенко @
                          Таким образом механизм шаблонов очень ограничен и его можно безопасно юсать только с простейшими типами


                          Ну да. Или с другими типами, которые эти самые простейшие типы эмулируют.

                          Вот смотрите, есть три кита, на котором стоит C++.
                          1. стандартные контейнеры;
                          2. стандартные алгоритмы;
                          3. итераторы которые их связывают.

                          Алгоритмы, обычно, на вход просят нечто похожее на указатели. Если дать им указатели, то всё работает нормально.
                          Шаблоны функций, разрешают передавать любой тип, лиш бы он вёл себя как указатель.

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

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

                          Но вот чудно-то как. В стандартной библиотеке огромная куча шаблонов. Оно всё друг с другом работает, взаимодействует.
                          Так что ваша реплика очень голословная. А тех кто знает, очень сильно смешит.

                          Ах да, кроме стандартной библиотеки есть ещё другие библиотеки, и ведь тоже на шаблонах! Всякие boost, atl, wtl и так далее.

                          Добавлено
                          Цитата Flex Ferrum @
                          мужики давным давно придумали концепты

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

                          Это сообщение было перенесено сюда или объединено из темы "А правда "шаблоны" - это совершенно отдельная тема в программировании на С++?"
                            Очень доступно и просто объяснил саша от концепта к лайт концепту

                            Это сообщение было перенесено сюда или объединено из темы "А правда "шаблоны" - это совершенно отдельная тема в программировании на С++?"
                              В D вместо концептов есть template constraints, не так выразительно как концепты, зато не сбивает с толку:
                              ExpandedWrap disabled
                                void foo(R)(ref const R range) if(isRandomAccessRange!R) {
                                   ...
                                }

                              как я понимаю, в плюсах с концептами аналогичный код будет выглядеть как-то так:
                              ExpandedWrap disabled
                                void foo(const RandomAccessRange& range) {
                                    ...
                                }

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

                              Это сообщение было перенесено сюда или объединено из темы "А правда "шаблоны" - это совершенно отдельная тема в программировании на С++?"
                              Сообщение отредактировано: applegame -
                                Цитата applegame @
                                При взгляде на плюсовой вариант даже не понятно, что это шаблон и что RandomAccessRange - это концепт, а не какой-то юзерский тип. Может это не будет мешать, хз, но мне это дело кажется стрёмным.

                                Я руками, для своих нужд, замутил концепт.
                                Использовать именно так, как вы написали. Поскольку я использовал стандартные языковые конструкции.
                                Это действительно пользовательский тип, который обёртывает и проверяет другой тип.
                                Но да, наверное, надо как-то обозначать тип концепта. Чтоб люди не пугались.
                                Я бы предложил суфикс "_concept", для всех типов представляющих концепты.

                                Это сообщение было перенесено сюда или объединено из темы "А правда "шаблоны" - это совершенно отдельная тема в программировании на С++?"
                                Сообщение отредактировано: Eric-S -
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0648 ]   [ 16 queries used ]   [ Generated: 24.04.24, 18:23 GMT ]