На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS

Дорогие друзья! Поздравляем вас с Новым 2025 годом!

Всем удачи, успеха и благополучия!

msm.ru
! Правила раздела:
1. Название темы - краткое описание кто/что против кого/чего
2. В первом сообщении - список параметров, по которым идет сравнение.
3. Старайтесь аргументировать свои высказывания. Фразы типа "Венда/Слюникс - ацтой" считаются флудом.
4. Давайте жить дружно и не доводить обсуждение до маразма и личных оскорблений.
Модераторы: Модераторы, Комодераторы
Страницы: (17) « Первая ... 14 15 [16] 17  все  ( Перейти к последнему сообщению )  
> WinAPI и POSIX , бой насмерть
    Цитата Majestio @
    В языках программирования нового поколения (Dart, и как оказалось, и Swift) ввели понятие "именованных параметров". Там это решается проще - просто при инициализации указываем те параметры, которые явно нужно определить (по именам параметров), остальные инициализируются по умолчанию.
    Что тебе мешает то же самое напрограммить на Плюсах? Пишешь один раз шаблон, при конкретизации инстанцируешь набором параметров, при использовании зовёшь метод шаблона, который переводит сие в процедурный вызов. Не скажу, что это легко и быстро, но один раз же. Только потом не огорчайся, когда народ будет реагировать на это как ты на ту хабровую статью про эрроры. Оно надо будет буквально паре человеков.
    Я в общем-то могу повторить про чемлучшемульёнполей буквально:
    Скрытый текст
    ExpandedWrap disabled
      struct
      {
          LPCSTR lpApplicantName,
          LPCSTR lpPropertyAddress,
          LPCSTR lpLoanType,
          double dLoanAmount,
          int nLoanTerm,
          double dInterestRate,
          BOOL bFixedRate,
          LPCSTR lpCreditScore,
          LPCSTR lpEmploymentStatus,
          LPCSTR lpIncomeVerification,
          BOOL bCoApplicant,
          LPCSTR lpCoApplicantName,
          LPCSTR lpCoApplicantCreditScore,
          LPCSTR lpDownPaymentSource,
          double dDownPaymentAmount,
          LPCSTR lpPropertyType,
          BOOL bFirstTimeHomeBuyer,
          LPCSTR lpLoanOfficerName,
          LPCSTR lpApplicationID,
          BOOL bPreApproval,
          LPCSTR lpReferralSource,
          LPCSTR lpContactMethod,
          BOOL bEmailUpdates,
          LPCSTR lpPreferredClosingDate,
          LPCSTR lpInsuranceProvider,
          LPCSTR lpPropertyInspectionStatus,
          LPCSTR lpAppraisalValue,
          BOOL bEscrowAccount,
          LPCSTR lpMonthlyPaymentEstimate,
          LPCSTR lpLoanDisclosureDocuments,
          LPCSTR lpAdditionalNotes,
          BOOL bSubmitApplication
      ) SuperCoolStruct_VS_DeepShitParams, *PSuperCoolStruct_VS_DeepShitParams;
       
      BOOL OpeningMicrosoftMortgage(PSuperCoolStruct_VS_DeepShitParams cfg);
    и напомнить, что memset() (неважно, что подкапотный) не решает траблю, т.к. далеко не всегда нулевая последовательность бит подходит для значения по умолчанию. Я поступлю по другому, а именно спрошу "дорогой Majestio, откуда у тебя выродилась такая гора входов в одну подсистему?", а потом "как система защищена от человеческого фактора? как она реагирует на случайный пропуск инициализации одного поля? а двух? а десятка потому что скопипастил, и поправил со сдвигом в две строки?" Я об этом уже писал выше, третий раз не буду.
    Цитата D_KEY @
    Ты сам пишешь про rtos, но винда к ним не относится
    Ты возможно удивишься, но ядро у винды на порядок более реалтаймое, чем у линукса. Я даже под Win98SE в своё время получал гарантированные микросекунды реакции, тогда как соседний nix-овый отдел оперировал миллисекундами. Под WinXP ситуация не поменялась, а как нынче у того отдела, беспонятия, меня в том КБ уже 20 лет нету. И не надо, что мол ядро и прикладной уровень не сравнимы. Да, не сравнимы, но прикладное ПО с требованиями жёсткого реал-тайма и проектируются соответственно, одного только наличия RTOS недостаточно.
    Цитата D_KEY @
    Может раньше была какая-то старая и другая, а сейчас перешли на что-то новое?
    Скорее просто случайное совпадение аббревиатур. Хотя вариант с развитием ОСи в направлении мультиплатформенности тоже может быть. Тогда действиетльно Honeywell могла взять что-то старое и 20 (?) лет использовать в своих продуктах, а ОСь с тех пор эволюционировала. На тот момент в тестируемых нами шелезяках были P5 и i486.
    Цитата D_KEY @
    Ты хочешь сказать, что в их "RTOS" под капотом была винда?
    Нет. Что её API основан на WinAPI. Реализация ОСи в лучшем случае (не факт, ессно) была лицензирована с Windows CE, которая, как известно, с Windows, кроме API, общего ничего не имеет. Это тем более вероятно, что даже их тестовая среда TATS использовала VBScript под лицензией с некоторыми расширениями языка типа групп, драйверов, мониторов итп. (Это всё не те группы, драйверы и мониторы в известном смысле, это названия подсистем тестирования, управляющие входами и контролирующие выходы.)
    Цитата D_KEY @
    Тут проблема в том, что в публичной информации нет никакого упоминания про windows, есть информация про разные rtos и они основаны не на винде, а или на чем-то своем или на линуксах.
    Ты невнимательно меня читаешь, кажись. Я говорил не об изделиях, а о средствах их разработки, верификации и сертификации. Изделия-то зачастую работают вообще на чём-то самописном, где и POSIX даже близко не наблюдается.
    Сообщение отредактировано: Qraizer -
      Цитата Qraizer @
      Я говорил не об изделиях, а о средствах их разработки, верификации и сертификации.

      А, ну тогда это вообще большого значения не имеет, ИМХО. На чем угодно можно разрабатывать :-?

      Добавлено
      Цитата Qraizer @
      Изделия-то зачастую работают вообще на чём-то самописном, где и POSIX даже близко не наблюдается.

      Ну судя по тому, что гуглится, вполне себе наблюдается :)
      Сам я довольно мало работал с rtos и давно. Но это был ecos, который posix слой предоставлял.

      Ну и мы все упёрлись зачем-то в очень узкую нишу.

      Пока считаю свой тезис о том, что POSIX таки является стандартом для ОСей и таки реально реализуется и используется, верным.
      Точно так же как тезис о том, что winapi подобным стандартом не является и потому сравнивать это с posix некорректно.
      Сообщение отредактировано: D_KEY -
        Цитата Qraizer @
        Что тебе мешает то же самое напрограммить на Плюсах?
        ...
        Только потом не огорчайся, когда народ будет реагировать на это как ты на ту хабровую статью про эрроры. Оно надо будет буквально паре человеков..

        Сам же и ответил. И не надо делать вывод, что раз костылями для реализации концепции не пользуются, то и сама концепция не нужна. Я помню, как люди плевались на бустовые лямбды, например. Но как только лямбды появились в языке (стандарте), то почему-то все начали пользоваться.
        Потому что проблема в самих костылях, а не концепции.

        Добавлено
        Цитата Qraizer @
        Я в общем-то могу повторить про чемлучшемульёнполей буквально.

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

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

        Не знаю, что там в windows. Линукс раньше и не был rtos, были отдельные версии linux для rtos. Сейчас, насколько я знаю, linux умеет работать в real time режиме (вроде в этом году смержили наконец-то патчи, которые жили много лет отдельно). Для windows это не так :)
        Сообщение отредактировано: D_KEY -
          Цитата Qraizer @
          Что тебе мешает то же самое напрограммить на Плюсах? Пишешь один раз шаблон, при конкретизации инстанцируешь набором параметров, при использовании зовёшь метод шаблона, который переводит сие в процедурный вызов. Не скажу, что это легко и быстро, но один раз же. Только потом не огорчайся, когда народ будет реагировать на это как ты на ту хабровую статью про эрроры. Оно надо будет буквально паре человеков.

          Не, спасибо. Это мне кажется не одно и тоже. А тем более вплетать для этого метапрограммирование - ваще беда. И, если честно, я не совсем понимаю как у тебя это получится. Можешь продемонстрировать?

          Цитата Qraizer @
          Я поступлю по другому, а именно спрошу "дорогой Majestio, откуда у тебя выродилась такая гора входов в одну подсистему?", а потом "как система защищена от человеческого фактора? как она реагирует на случайный пропуск инициализации одного поля? а двух? а десятка потому что скопипастил, и поправил со сдвигом в две строки?" Я об этом уже писал выше, третий раз не буду.

          Вот в этом и фишка подхода в Dart - кроме "поименованной" инициализации есть еще возможность объявлять обязательные и необязательные параметры. Случайного пропуска не будет - компилятор не даст. А если пропустили "необязательный", то у него обязана быть инициализация по умолчанию, или он инициализируется null. Т.е. тут большая ответственность лежит на том, кто написал такую функцию, конструктор или метод. У того, кто пользует - все гарантии есть. А про количество аргументов ... более 5-7 (или около того) я считаю извратом. Я о таком уже писал выше. Но всяко же бывает.
            Цитата Qraizer @
            Ты возможно удивишься, но ядро у винды на порядок более реалтаймое, чем у линукса.

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

            Понятие "RTOS" не подразумевает оценку отклика системных вызовов, или качества планировщика многозадачности, или еще чего-то (допустим цвета упаковки коммерческого дистра). Да, если эти параметры на высоте - это супер. Но самое главное отличие обычной оси от RTOS, в том, что RTOS гарантирует и предоставляет прогеру возможности прогать вызовы в строго детерминированных промежутках времени. В Уиндовс такого не было, нет, и пока слабо ожидается! Хотя Гугыль подсказывает - подвижки есть. Пример Windows 10 IoT Enterprise, в котором частично реализовано т.н. "мягкое реальное время". Иными словами, часть возможностей реализована.

            Что касается Люникса

            Люникс - это не операционная система (это, по сути, просто ядро)! А вот моя любимая Фряха - это полноценная ось. Операционной системой Люникс может быть только в составе дистра(ов). Тогда да.

            Что касается RTOS Люникса

            Я не слышал по полноценных, 100% перепатченых дистров под реальное время. Да, есть отдельные "флагманы", типа RTLinux, FreeRTOS, Xenomai (но это отдельный догружаемый проект). Таким образом ... пшик :lol: Но есть одно "но", ну достаточно продолжительное время начинают выпускаться ядра Люникса, разделённые на "обычные" и "RT". Пример из моего любимого дистра Manjaro (в красных рамках выделены рилтаймовские ядра):

            Прикреплённая картинка
            Прикреплённая картинка


            И, тем не менее ... Даже если я RT-ядро установлю - от этого моя ось полноценной RTOS не станет! Ядро просто предоставляет для рилтайма низкоуровнёвый интерфейс, ко всем прочим интерфейсам. Как мы определились выше (вернее, я вас определил) - ось это ядро + базовый, коробочный, набор софта. Так вот, если это набор на RT плевать хотел, о какой рилтаймовости может идти речь?

            Все, что писал выше - чисто знакомство последних дней. Понимаю, что по верхам, понимаю, что мог где-то ошибиться. Но чуйка меня редко подводит.
              Цитата D_KEY @
              Ну судя по тому, что гуглится, вполне себе наблюдается
              Ты можешь нагуглить в лучшем случае прототипы систем бортового управления (сиречь менеджмента). У них 100пудово категория E, по которой сертификация требует базовый набор документов из двух комплектов, и на этом всё. Только Р4754 или может быть 4761. Развернуть прототип и связать с компонентами не проблема. Потому что DAL-E не влияет на безопасность. Мы же говорим о компонентах класса 3А или 3Б с категориями через одного DAL-A/B и C и только изредка D. По ним из стандартов не вылезешь, комплектов документов потребуется 3 десятка по каждому, и их на борту сотни. Не все из них используют ПО, многие только электронные или даже электрические, а некоторые вообще просто механика. Но это неважно, те, которые используют ПО, ты даже близко не нагуглишь. Их вне каналов взаимодействия между сертифицирующими органами и разработчиками, включая подрядчиков, нигде нет... а, ну ещё в архивах.
              Вот конкретно сейчас мы занимаемся системой торможения для МС-21. Там четыре (хоть и все ARM, но все разные) микроконтроллера с FLASH на 512Кб и 128Кб RAM. Ну-ну запихать туда что-нить не самописное. И оно на 80% состоит из взаимодействия с железом и остальные 20% чутка логики для обхода отказов, включая события единичного отказа. Самолёты целиком состоят из вот таких на наш/ваш взгляд примитивных вычислительных модулей. Что-либо более-менее серьёзное, хотя бы уровня P5M или там Qualcomm S1, которые мы всерьёз не воспринимаем уже лет 10-20, ставят на что-нибудь сугубо интерфейсное или в салон мультики пассажирам крутить. Просто потому что они ненадёжны, и утеря ими функциональности некритична. Вот это ты можешь нагуглить тоннами, это бизнес. P.S. Бизнес – не безопасность.

              Добавлено
              Цитата D_KEY @
              Я помню, как люди плевались на бустовые лямбды, например.
              Хм. Лично я помню, что очень сильно плевался на буст, потому что таскать за собой его было накладно, но не лямбды. За лямбды я сожалел, что они хоть и гораздо удобнее функторов, но всё ж недостаточно и ввиду слабой языковой поддержки их эффективность хуже. Но на C++03 большего и не сделать было. Как концепция лямбды мне очень нравились. В отличие от именованных аргументов, натянуть на каковые объективный смысл весьма затруднительно. Те же пропертя, только горизонтально.

              Добавлено
              Цитата D_KEY @
              Но в любом случае, это лучше тем, что ты можешь про инициализировать один раз и дальше отправлять в нескольких местах без копипасты.
              Ну, за копипасту я слегонца слукавил всё ж. Обычно, если нужен однотипный код в нескольких местах, где копипаста помогает, там нет мульёна параметров или полей структур. Скажем так: мне не приходилось запускать процессы пачками. А с другой стороны, там, где тебе нужно запустить процесс, довольно сложно сделать это поэтапно, ибо старт процесса – это фактически его конструктор. Разделение создания объекта и его последующей инициализации давно уж признано не самым лучших аспектом ООП-модели, ибо в промежутке между этими этапами объект как ресурс существует, но отсутствует как сущность. Так что всё настраиваемые параметры нового процесса нужны здесь и сейчас, а не потом когда-нибудь.
                Цитата Majestio @
                А тем более вплетать для этого метапрограммирование - ваще беда. И, если честно, я не совсем понимаю как у тебя это получится. Можешь продемонстрировать?
                Именно метой. А для чего её по-твоему в язык ввели впрочем да, ввели-то ещё в C++98 случайно, но вот развили в C++11 уже намерено.
                Продемонстрировать... ишь ты. Ну как концепт, можно.
                Цитата Majestio @
                Вот в этом и фишка подхода в Dart - кроме "поименованной" инициализации есть еще возможность объявлять обязательные и необязательные параметры.
                Ну так я говорю, Dart переизобрёл MSное OLE Automation, которой 100 лет в обед.

                Добавлено
                Цитата Majestio @
                Понятие "RTOS" не подразумевает оценку отклика системных вызовов, или качества планировщика многозадачности, ... Но самое главное отличие обычной оси от RTOS, в том, что RTOS гарантирует и предоставляет прогеру возможности прогать вызовы в строго детерминированных промежутках времени. В Уиндовс такого не было, нет, и пока слабо ожидается!
                Вот в этом ты ошибаешься. RTOS гарантирует времена откликов. Они не обязательно какие-то там маленькие, микросекунды или что там, но они точно гарантировано не более чем вот такие-то. Винда на уровне ядра это гарантирует посредством уровней IRQL.
                  Цитата Majestio @
                  RTOS гарантирует и предоставляет прогеру возможности прогать вызовы в строго детерминированных промежутках времени

                  Цитата Qraizer @
                  Вот в этом ты ошибаешься. RTOS гарантирует времена откликов.

                  Ну так это какгбэ одно и тоже, только разными словами :blink: Под гарантией понимается возможность задания времён/таимаутов исполнения.

                  Цитата Qraizer @
                  Винда на уровне ядра это гарантирует посредством уровней IRQL.

                  Для такой гарантии в WinAPI должны присутствовать системные вызовы с явным указанием желаемых тайм-аутов на исполнение. Оно там действительно есть?

                  Цитата Qraizer @
                  Ну так я говорю, Dart переизобрёл MSное OLE Automation, которой 100 лет в обед.

                  Дело не в изобретении, а во включении в стандарт языка. Вон там, к примеру, подымали тему лямбд. Тоже могу сказать, что С++ в 2011 году их не изобрели, но их включили в стандарт языка. Я лямбды в Perl пользовал еще в далеком 1997 году, сразу как изучил и начал пользоваться. А сам, еще тогдашний Perl 4, релизнулся в 1993 году.
                    Цитата Majestio @
                    Я не слышал по полноценных, 100% перепатченых дистров под реальное время.

                    Вроде были. Плюс сейчас в этом году в ядро смержили поддержку реального времени.

                    Добавлено
                    Цитата Qraizer @
                    Ты можешь нагуглить в лучшем случае прототипы систем бортового управления (сиречь менеджмента). У них 100пудово категория E, по которой сертификация требует базовый набор документов из двух комплектов, и на этом всё. Только Р4754 или может быть 4761. Развернуть прототип и связать с компонентами не проблема. Потому что DAL-E не влияет на безопасность. Мы же говорим о компонентах класса 3А или 3Б с категориями через одного DAL-A/B и C и только изредка D. По ним из стандартов не вылезешь, комплектов документов потребуется 3 десятка по каждому, и их на борту сотни. Не все из них используют ПО, многие только электронные или даже электрические, а некоторые вообще просто механика. Но это неважно, те, которые используют ПО, ты даже близко не нагуглишь. Их вне каналов взаимодействия между сертифицирующими органами и разработчиками, включая подрядчиков, нигде нет... а, ну ещё в архивах.
                    Вот конкретно сейчас мы занимаемся системой торможения для МС-21. Там четыре (хоть и все ARM, но все разные) микроконтроллера с FLASH на 512Кб и 128Кб RAM. Ну-ну запихать туда что-нить не самописное. И оно на 80% состоит из взаимодействия с железом и остальные 20% чутка логики для обхода отказов, включая события единичного отказа. Самолёты целиком состоят из вот таких на наш/ваш взгляд примитивных вычислительных модулей. Что-либо более-менее серьёзное, хотя бы уровня P5M или там Qualcomm S1, которые мы всерьёз не воспринимаем уже лет 10-20, ставят на что-нибудь сугубо интерфейсное или в салон мультики пассажирам крутить. Просто потому что они ненадёжны, и утеря ими функциональности некритична. Вот это ты можешь нагуглить тоннами, это бизнес. P.S. Бизнес – не безопасность.

                    Я с тобой во многом не согласен. Но кажется, что это все не имеет отношения к теме дискуссии :)
                    Так что тут можно закончить. Ты в этом веришся, тебе виднее, наверное.
                    Узкая ниша (плюс ещё и перекос на российскую специфику, а я не уверен, что она отражает мировые тренды). Не вижу смысла обсуждать тут, оно не имеет отношения к winapi vs posix.

                    Добавлено
                    Цитата Qraizer @
                    За лямбды я сожалел, что они хоть и гораздо удобнее функторов, но всё ж недостаточно и ввиду слабой языковой поддержки их эффективность хуже. Но на C++03 большего и не сделать было. Как концепция лямбды мне очень нравились.

                    Ну так я и говорю, что костыльность реализации не означает то, что концепция плоха.

                    Добавлено
                    Цитата Qraizer @
                    В отличие от именованных аргументов, натянуть на каковые объективный смысл весьма затруднительно

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

                    Добавлено
                    Цитата Qraizer @
                    Винда на уровне ядра это гарантирует посредством уровней IRQL.

                    А можно какую-то ссылку на документацию?
                    Сообщение отредактировано: D_KEY -
                      Цитата Majestio @
                      Для такой гарантии в WinAPI должны присутствовать системные вызовы с явным указанием желаемых тайм-аутов на исполнение. Оно там действительно есть?
                      В WinAPI нет, но оно и не RT. Ты тоже невнимателен, я говорил за ядро ОСи. В ядре винды RT вполне себе есть.
                      Но следует учитывать, конечно, что она никогда не позиционировалась как RTOS, поэтому гарантий MS не предоставляет. И тем не менее анализ ядерного API показывает, что чёткое вытеснение на основе приоритетов там присутствует, и практика это подтверждает ну, не опровергает.
                      Цитата D_KEY @
                      Узкая ниша (плюс ещё и перекос на российскую специфику, а я не уверен, что она отражает мировые тренды). Не вижу смысла обсуждать тут, оно не имеет отношения к winapi vs posix.
                      За российскую специфику это ты зря. Как раз российская специфика, особенно с недавних пор, должна бы по идее убить в себе зависимость от проприетарных технологий недружественных стран, ан нет. Не то что не смогли, даже не собирались начинать. Только тс-с-с, не дай бог нас там услышат. Оффтоп, конечно, но напомню, что речь об этом зашла в контексте надёжности и безопасности ПО, а этот контекст появился от меня как практическая демонстрация безопасности APIs. И мне правда жаль, что из соображений конфиденциальности интеллектуальной собственности (в частности не нашей, а заказчиков) не могу предоставить что-нибудь более материальное.

                      В общем, я тут сварганил на коленке концепцию.
                      ExpandedWrap disabled
                        #include <source_location>
                        #include <iostream>
                        #include <functional>
                        #include <type_traits>
                        #include <cstring>
                         
                        template <typename Param> struct Node
                        {
                          using value_type = Param;
                         
                          static value_type set(value_type& l, const value_type& r) { return l = r; }
                          static value_type get(const value_type& v)                { return v;     }
                         
                          static inline const value_type default_value = value_type{};
                        };
                         
                        template <typename T, std::uint_least32_t L, std::uint_least32_t C> struct Value_Base
                        {
                          static const std::uint_least32_t line   = L;
                          static const std::uint_least32_t column = C;
                         
                          using node_type = Node<T>;
                          using value_type= typename node_type::value_type;
                         
                          value_type value;
                         
                          Value_Base(): value(node_type::default_value) {}
                          Value_Base& operator=(const typename node_type::value_type& v) { value = v; return *this; }
                        };
                        template <typename T, std::uint_least32_t L, std::uint_least32_t C> struct Value;
                         
                        #define Prop_Decl(Type)                                          \
                        struct Value<typename Type::node_type::value_type, Type::line, Type::column>
                         
                        #define Prop_Impl(Type)                                                                         \
                        template<>                                                                                      \
                        struct Value<typename Type::node_type::value_type, Type::line, Type::column>: public Type       \
                        {                                                                                               \
                        public:                                                                                         \
                          using node_type = typename Type::node_type;                                                   \
                          using value_type= typename node_type::value_type;                                             \
                          value_type Name;                                                                              \
                                                                                                                        \
                        public:                                                                                         \
                          explicit Value(const value_type& v = node_type::default_value): Name(v) {}                    \
                        };
                         
                        #define Prop(Type)                                                                              \
                        typedef struct Value_Base<Type, std::source_location::current().line(),                         \
                                                       std::source_location::current().column()>
                         
                        #define MakeProps(CurProp, ...)   Prop_Impl(CurProp) __VA_OPT__(Prop_Impl(__VA_ARGS__))
                        #define MakeBuilder(Func, CurProp, ...) Builder<Func, Prop_Decl(CurProp) __VA_OPT__(, Prop_Decl(__VA_ARGS__))>
                         
                        template <typename F, typename Param, typename ...NextParams>
                        struct Builder: public Param, public Builder<F, NextParams...>
                        {
                          template <typename Args>
                          void setArgs(Args &&args)
                          {
                            auto &value= static_cast<Value<typename std::remove_cvref_t<Args>::node_type::value_type,
                                                                    std::remove_cvref_t<Args>::line,
                                                                    std::remove_cvref_t<Args>::column>&>(*this);
                            using node_type = typename std::remove_reference_t<decltype(value)>::node_type;
                         
                            node_type::set(value.Name, args.value);
                          }
                         
                          auto doIt()
                          {
                            auto &value= static_cast<Value<typename std::remove_cvref_t<Param>::node_type::value_type,
                                                                    std::remove_cvref_t<Param>::line,
                                                                    std::remove_cvref_t<Param>::column>&>(*this);
                            using node_type = typename std::remove_reference_t<decltype(value)>::node_type;
                         
                            return node_type::get(value.Name);
                          }
                         
                          explicit Builder(F f): Builder<F, NextParams...>(f) {}
                         
                          template <typename Arg, typename ...Args>
                          typename std::function<F>::result_type operator()(Arg arg, Args... args)
                          {
                            setArgs(arg); (setArgs(args), ...);
                            return (this->fn)(doIt(), Builder<F, NextParams...>::doIt());
                          }
                        };
                         
                        template <typename F, typename Param>
                        struct Builder<F, Param>: public Param
                        {
                          template <typename Args>
                          void setArgs(Args &&args)
                          {
                            auto &value= static_cast<Value<typename std::remove_cvref_t<Args>::node_type::value_type,
                                                                    std::remove_cvref_t<Args>::line,
                                                                    std::remove_cvref_t<Args>::column>&>(*this);
                            using node_type = typename std::remove_reference_t<decltype(value)>::node_type;
                         
                            node_type::set(value.Name, args.value);
                          }
                         
                          auto doIt()
                          {
                            auto &value= static_cast<Value<typename std::remove_cvref_t<Param>::node_type::value_type,
                                                                    std::remove_cvref_t<Param>::line,
                                                                    std::remove_cvref_t<Param>::column>&>(*this);
                            using node_type = typename std::remove_reference_t<decltype(value)>::node_type;
                         
                            return node_type::get(value.Name);
                          }
                         
                          std::function<F> fn;
                         
                          explicit Builder(F f): fn(f) {}
                         
                          template <typename Args>
                          typename std::function<F>::result_type operator()(Args args)
                          {
                            setArgs(args);
                            return (this->fn)(doIt());
                          }
                        };
                         
                        Prop(const char*) param1;
                        Prop(const char*) param2;
                         
                        MakeProps(param1, param2);
                        MakeBuilder(decltype(strcmp), param1, param2) build(strcmp);
                         
                        int main()
                        {
                          std::cout << build(param1() = "abc", param2() = "abc") << std::endl;
                          std::cout << build(param1() = "abc", param2() = "abd") << std::endl;
                          std::cout << build(param2() = "abd", param1() = "abc") << std::endl;
                          std::cout << build(param1() = "abd")                   << std::endl;
                          std::cout << build(param2() = "ab" )                   << std::endl;
                        }
                      Недостатков уйма. Значения по умолчанию по сути не работают (последние два вызова), т.к. задаются только в начале и когда позже перебиваются явными значениями, такими и остаются. Много избыточного, т.к. это третья по счёту наконец-то заработавшая как надо реализация, и мне лень её вычищать и оптимизировать. В конце концов это концепция, а не либа. И да, давненько я не брал в руки препроцессор :D ... Кто если заинтересуется, может заглянуть в мои мультиметоды на гитхабе и стащить оттуда нормальные техники реализации этого безобразия, без препроцесора, со списками типов, нормальной рекурсией по параметрам и деревьям акцепторов. Зато тут уже заложен потенциал стратегии для кастомизации обработки специфических типов параметров (на основе template <typename Param> struct Node) и уже реализована неограниченная N-arity с произвольным порядком передачи параметров в вызов. Второй и третий вызовы показывают, что порядок параметров Builder не влияет на порядок параметров strcmp().
                      Но лучше, думаю, подождать C++26, куда нам обещали крутейшую рефлексию. Не факт, что успеют, правда.
                      Сообщение отредактировано: Qraizer -
                        Цитата Qraizer @
                        В общем, я тут сварганил на коленке концепцию.

                        Как всегда :lol: Даже разбираться не буду, мне страшно :lol:

                        Ну я тоже решил сварганить свой подход:

                        ExpandedWrap disabled
                          #include <iostream>
                          #include <any>
                          #include <map>
                           
                          enum class KeyType {
                            One, Two, Three
                          };
                           
                          using ParamsType = std::map<KeyType, std::any>;
                           
                          void TestFunc(ParamsType param) {
                            for(const auto &i: param) {
                              std::cout << "param [";
                              switch(i.first) {
                                case KeyType::One:   std::cout << "One]: "   << std::any_cast<std::string>(i.second); break;
                                case KeyType::Two:   std::cout << "Two]: "   << std::any_cast<int>(i.second); break;
                                case KeyType::Three: std::cout << "Three]: " << std::any_cast<double>(i.second); break;
                                default:             std::cout << "Unknown]";        
                              }
                              std::cout << std::endl;  
                            }
                          }
                           
                          int main() {
                            TestFunc({
                              {KeyType::Two, 2},        
                              {KeyType::One, std::string{"Один"}},
                              // можно пропустить, а можно не пропустить {KeyType::Three, 2.71828}
                            });
                            return 0;
                          }

                        ExpandedWrap disabled
                          param [One]: Один
                          param [Two]: 2

                        Позволяет какбэ реализовать именованные параметры, и позволяет параметрам быть необязательными. Но недостатков тоже масса:

                        1) Гораздо многословнее чем в Dart
                        2) Проверку наличия обязательных параметров можно обеспечить только проверками в рантайме в теле функции/конструктора/метода
                        3) Инициализацию по-умолчанию можно реализовать только в рантайме в теле функции/конструктора/метода
                        4) Чтобы не ошибиться в передаче и последующей обработке имен параметров пришлось запилить enum class

                        Цитата Qraizer @
                        Недостатков уйма.

                        И еще один недостаток ;) Я не смог твой пример откомпилячить тут - https://www.onlinegdb.com. Свой пример я проверил, для С++17.
                          Qraizer, норм вроде (позже гляну повнимательнее). Но, сам понимаешь, костыли это все :D

                          Есть уже boost.parameter. Но тоже костыли (особенно страшно выглядит объявление функций).

                          Добавлено
                          Majestio, в твоём варианте оверхед в рантайме, что для синтаксического сахара плохо :)
                          Сообщение отредактировано: D_KEY -
                            Цитата D_KEY @
                            Majestio, в твоём варианте оверхед в рантайме, что для синтаксического сахара плохо

                            Согласен, вааще не вопрос! :rolleyes:
                              D_KEY, это не костыли, это расширение возможностей языка его же средствами. С тем же успехом можно назвать костылями все эти <type_traits>, <ratio> итп.
                              Идея в том, что построенное на основе шаблонного вариадика дерево Builder содержит узлы Value для хранения переданных параметров, которые в свою очередь унаследованы от Value_base, хранящие значения по умолчанию. На случай особых типов, чтение и установка параметра вынесено в стратегию Node, которая легко специализируется. (Например, для указателей может захотеться намутить контейнер, владеющий контентом, вместо хранения собственно указателя.) Каждый Value_base уникален, благодаря зависимости от строки/колонки в сырце, и производный от него Value наследует зависимость от строки/колонки, позволяя работать с Value_base уже без этой зависимости. Каждый Value представлен в дереве Builder отдельный узлом, так что static_cast<> легко кастует Builder вниз к нужному Value. В вызове Builder создаются лёгкие rvalue этих Value_base, которые заменяют значения по умолчанию из Node на указанные, и Builder сначала последовательно проходит по всем переданным Value_base (извлекая инфу для зависимого от него Value из своего дерева), переносит значения из них в найденные у себя Value, а затем проходит по своим Value уже в порядке шаблонных параметров и собирает вариадиком значения для передачи в функцию. Конечно, надо бы ещё добавить в Node какие-нибудь set_default/get_default() для управления умолчаниями в ран-тайм и сброс значений Value к хранимым в Node, чтоб совсем шоколадно.
                              Посмотри, там оверхеда нет вообще:
                              ExpandedWrap disabled
                                int main()
                                {
                                00007FF6363C96F0  push        rbx  
                                00007FF6363C96F2  sub         rsp,20h  
                                  std::cout << build(param1() = "abc", param2() = "abc") << std::endl;
                                00007FF6363C96F6  mov         rcx,qword ptr [build+58h (07FF6364C3B28h)]  
                                00007FF6363C96FD  lea         rbx,[string "%p" (07FF63649A6CCh)]  
                                00007FF6363C9704  mov         qword ptr [build+8h (07FF6364C3AD8h)],rbx  
                                00007FF6363C970B  mov         qword ptr [build+18h (07FF6364C3AE8h)],rbx  
                                00007FF6363C9712  mov         qword ptr [rsp+30h],rbx  
                                00007FF6363C9717  mov         qword ptr [rsp+38h],rbx  
                                00007FF6363C971C  test        rcx,rcx  
                                00007FF6363C971F  je          main+1B5h (07FF6363C98A5h)  
                                00007FF6363C9725  mov         rax,qword ptr [rcx]  
                                00007FF6363C9728  lea         r8,[rsp+30h]  
                                00007FF6363C972D  lea         rdx,[rsp+38h]  
                                00007FF6363C9732  mov         qword ptr [rsp+40h],rdi  
                                00007FF6363C9737  call        qword ptr [rax+10h]  
                                00007FF6363C973A  mov         edx,eax  
                                00007FF6363C973C  lea         rcx,[std::cout (07FF6364C5B70h)]  
                                00007FF6363C9743  call        std::basic_ostream<char,std::char_traits<char> >::operator<< (07FF6363B1D70h)  
                                00007FF6363C9748  mov         rcx,rax  
                                00007FF6363C974B  call        std::endl<char,std::char_traits<char> > (07FF6363B1320h)  
                                  std::cout << build(param1() = "abc", param2() = "abd") << std::endl;
                                00007FF6363C9750  mov         rcx,qword ptr [build+58h (07FF6364C3B28h)]
                              Если включить -O2, конечно. Точнее, он есть, принадлежит std::function<>, но разглядеть его непросто, чекает инкапсулированную функцию на nullptr.

                              Добавлено
                              Цитата Majestio @
                              И еще один недостаток Я не смог твой пример откомпилячить тут - https://www.onlinegdb.com.
                              std::source_location требует C++20. Кроме того, VS тоже ругается, если не указать ключик /Zc:preprocessor, который разрешает variadic macro... Хм, что-то у меня есть подозрение, что с препроцессором я облажался

                              Добавлено
                              P.S. На всякий случай результат исполнения:
                              ExpandedWrap disabled
                                0
                                -1
                                -1
                                0
                                1
                                Цитата Qraizer @
                                D_KEY, это не костыли, это расширение возможностей языка его же средствами.

                                Костыли. У C++ нет достаточных возможностей для расширения языка и добавления синтаксического сахара в данном случае (а такой способ передачи аргументов это именно синтаксический сахар). Препроцессор тут помог не сильно.
                                А по поводу идеи, да, кажется норм.
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0824 ]   [ 17 queries used ]   [ Generated: 20.01.25, 05:43 GMT ]