На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! Правила раздела:
1. Название темы - краткое описание кто/что против кого/чего
2. В первом сообщении - список параметров, по которым идет сравнение.
3. Старайтесь аргументировать свои высказывания. Фразы типа "Венда/Слюникс - ацтой" считаются флудом.
4. Давайте жить дружно и не доводить обсуждение до маразма и личных оскорблений.
Модераторы: Модераторы, Комодераторы
Страницы: (17) « Первая ... 15 16 [17]  все  ( Перейти к последнему сообщению )  
> WinAPI и POSIX , бой насмерть
    У C++ нет таких возможностей для того, что не может быть разрешено в компайл-тайм и требует линк-тайм. Например, полноценные мультиметоды. Но можно к такому приблизиться очень близко. Если ты имеешь в виду что-то типа рефлексии, то это уже не грамматика. Но её тоже обещают через пару лет, посмотрим
      Оказалось, что препроцессор я в руки брал ещё давнее, чем мне казалось. Мне было лень возиться со списками типов, но я вспомнил за вариадик-макросы, и думал, что они мне помогут. Не помогли. Вылетело из головы, что макросы в принципе нерекурсивны, и вариадики этого не изменяют. Так что нужно было бы по старинке, нумеровать 1, 2, 3 итд до нужного количества, которые бы ссылались на предыдущие.
      В общем пофик. Нате нормальную версию. Препроцессор остался только в определении параметров, потому что удобно. Но и там можно от него избавиться, если обеспечить уникальность типов свойств как-нибудь иначе.
      ExpandedWrap disabled
        #include <cstdint>
        #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 Type>
        struct Value: 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()>
         
        struct NullType{};
         
        template <typename T, typename H>             struct TList;
        template <typename T, typename L, typename R> struct TList<T, TList<L, R>>
        {
          using Node = T;
          using Tail = TList<L, R>;
        };
        template <typename T> struct TList<T, NullType>
        {
          using Node = T;
          using Tail = NullType;
        };
         
        template <typename N, typename ...Args> struct MakeList
        {
          using type = TList<Value<N>, typename MakeList<Args...>::type>;
        };
        template <typename N>                   struct MakeList<N>
        {
          using type = TList<Value<N>, NullType>;
        };
        template <typename N, typename ...T>
        using MakeTList = typename MakeList<N, T...>::type;
         
        template <typename N, typename ...T>
        using MakeProps = typename MakeTList<N, T...>::type;
         
        template <typename F, typename Param>
        struct Builder: public Param::Node, public Builder<F, typename Param::Tail>
        {
          template <typename Args>
          void setArgs(Args &&args)
          {
            auto &value     = static_cast<Value<std::remove_reference_t<Args>>&>(*this);
            using node_type = typename std::remove_reference_t<decltype(value)>::node_type;
         
            node_type::set(value.Name, args.value);
          }
         
          auto getValue()
          {
            auto &value     = static_cast<typename Param::Node&>(*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, typename Param::Tail>(f) {}
         
          template <typename ...Args>
          typename std::function<F>::result_type call(Args... args)
          {
            return Builder<F, typename Param::Tail>::call(args..., getValue());
          }
         
          template <typename ...Args>
          typename std::function<F>::result_type operator()(Args... args)
          {
            (setArgs(args), ...);
            return call();
          }
        };
         
        template <typename F>
        struct Builder<F, NullType>
        {
          std::function<F> fn;
         
          explicit Builder(F f): fn(f) {}
         
          template <typename ...Args>
          typename std::function<F>::result_type call(Args... args)
          {
            return (this->fn)(args...);
          }
        };
         
        void f(int x, int y, int z)
        {
          std::cout << x << '\t' << y << '\t' << z << std::endl;
        }
         
        Prop(const char*) param1;
        Prop(const char*) param2;
         
        Builder<decltype(strcmp), MakeTList<param1, param2>> build(strcmp);
         
        Prop(int) par1;
        Prop(int) par2;
        Prop(int) par3;
         
        Builder<decltype(f), MakeTList<par1, par2, par3>> f_proxy(f);
         
        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;
         
          f_proxy(par2() = 456, par1() = 789);
          f_proxy(par3() = 123);
        }
      Добавил функцию с тремя параметрами, чисто шоп потестить.

      Добавлено
      Majestio, разобрался с вашим доблестным компилером онлайн. Во-первых, ему нужно явное включение <cstdint>, чтобы были доступны определения типов типа uint_least32_t. Что очень странно, ибо этот тип используется в классе std::source_location, и он должен его включать сам. Ну ок, как бы не обязан, и как-то выкручивается. Во-вторых, ему категорически не травится атрибут noexcept у strcmp(), из-за которого он отказывается конкретизировать параметр std::function<> и идёт по обобщённой ветке, которая не реализована, и это правильно. Правильно, что не реализована для не подходящего типа, но вот то, что noexcept-функция является неподходящей – это ни разу не правильно. И это хороший вопрос к тамошней реализации STL, разбирайся с этой байдой сам, тут я не помощник. Во всяком случае ты можешь заменить std::function<> просто на указатель и везде вместо длинных bla_bla::return_type наставить auto. Должно работать, но это уж точно костыль.
      Сообщение отредактировано: Qraizer -
        Ещё костыльнее оказалось :)

        Добавлено
        В плане онлайн компиляторов, я лучше godbolt пока не видел.
          А что тогда не костыль с твоей точки зрения, D_KEY? Не, лучше не так. Дай определение термина "костыль", плз. Списки типов изобрёл Александреску, и ничего лучше пока не придумали. Да, есть вариадики, но это не эквивалент, т.к. их невозможно надёжно специализировать, постоянно выползают неоднозначности сопоставления, т.к. ... стремится попадать под что угодно. Автоматическую генерацию иерархий классов по спискам тоже он изобрёл, и что-то получше пока только обещают. Рекурсивный обход иерархии, применяя указанную стратегию к каждому узлу, опять же его заслуга. По факту весь шаблонный метапрогамминг от него, мои первые мультиметоды на C++03 зарелизились. Если подзабыл, то это изобретения более чем 20-летней давности, так что если б были намерения заменить на более другое, давно б уже зарелизили в Стандарте.

          Добавлено
          Цитата D_KEY @
          В плане онлайн компиляторов, я лучше godbolt пока не видел.
          Он не умеет C++20. Внезапно std::source_location ему неведом.
          Сообщение отредактировано: Qraizer -
            Цитата Qraizer @
            Цитата D_KEY @
            В плане онлайн компиляторов, я лучше godbolt пока не видел.
            Он не умеет C++20. Внезапно std::source_location ему неведом.

            А ты какой компилятор выбрал? А ключик прописал?

            Добавлено
            Цитата Qraizer @
            Дай определение термина "костыль"

            Хороший вопрос. На общее определение не претендую, но я бы сформулировал как "обходной путь для решения проблемы, который использует какие-то нестандартные и зачастую ненадежные инструменты, когда полноценное решение недоступно или слишком дорого". Как правило имеет ограничения и может привести к другим проблемам при использовании для решения исходной.
              Вот твой код с msvc и c /std:c++20

              Добавлено
              Цитата Qraizer @
              ему категорически не травится атрибут noexcept у strcmp(), из-за которого он отказывается конкретизировать параметр std::function<> и идёт по обобщённой ветке, которая не реализована, и это правильно. Правильно, что не реализована для не подходящего типа, но вот то, что noexcept-функция является неподходящей – это ни разу не правильно. И это хороший вопрос к тамошней реализации STL

              С этим интересно было бы разобраться, кстати. И gcc и clang не компилят. А они стандарту обычно следуют лучше msvc. На днях может быть посмотрю. Или если ты глянешь, то напиши.
              Сообщение отредактировано: D_KEY -
                Вообще, все верно, clang и gcc правы. std::function не умеет работать с noexcept функциями (а с C++17 они другой тип). Но твой код будет работать, если взять std::move_only_function из С++23 :)
                Сообщение отредактировано: D_KEY -
                  Цитата D_KEY @
                  На общее определение не претендую, но я бы сформулировал как "обходной путь для решения проблемы, который использует какие-то нестандартные и зачастую ненадежные инструменты, когда полноценное решение недоступно или слишком дорого
                  Ну т.е. ты сейчас обозвал костылями любые библиотеки. Ок.
                  И к слову, что ты имеешь против надёжности тут? Во-первых, это не библиотека, а только лишь концепт. Во-вторых, я бы не назвал свои мультиметоды ненадёжными. И они целиком и полностью отвечают Стандарту. Почитай их фичи. Как бы взятые оттуда решения не будут менее надёжными и в этом концепте.
                  У меня складывается впечатление, что ты просто не понимаешь, для чего вообще применяется метакод. Не открою большой секрет, если скажу, что как раз для того, чтобы научить компилятор делать то, что ранее он был делать не способен. Качество такого обучения естественно зависит от обучающего, так что костыли могут попадаться. Но не априори же.
                  Сообщение отредактировано: Qraizer -
                    Цитата Qraizer @
                    И они целиком и полностью отвечают Стандарту.

                    Не вдаваясь в подробности, и нагло влезая в ваш спич ... спешу сообщить - твой аргумент говно :lool: До той поры, когда в Стандарте будут явные ссылки на UB (а порой и неопубликованные и обсуждаемые) - это не будет "индульгенцией" для надёжности. Прости - просто логика :rolleyes:
                      Что б далеко не ходить, D_KEY, вот что на гитхабе написано:
                      Цитата
                      • header only lib;
                      • unbounded N-arity (except C++03, but very simply extendable);
                      • separate linkage type (static or dynamic) for each param;
                      • static linkage allow any types, any indirection (r-value refs included, excepting C++03 of course) and any cv-qualification (excepting r-value refs, I'm lazy);
                      • dynamic linkage also allow same, excepting param-by-value of course (but C++03 allow only cv-nonqualified pointers); you can use same or different class hierarchies for different dynamic params;
                      • simple and intuitive definition of dispatcher (C++03 is more comprehensive);
                      • you don't must to create full set of overriding combination for dynamic params; dynamic linkage uses rules of Standard overload rules; you will get a compile-time error on ambiguous or undecidability;
                      • base multimethod and all its overrides are encapsulated within one scope;
                      • no reinterpret_cast<>, no dynamic_cast<>;
                      • full params type control for static linkage params on entire path from dispatcher call to getting execution by multimethod; only Standard implicit conversions are allowed; (C++03 has some troubles there); no unneeded copies (but not for return value, sorry);
                      • great performance; Visitor (both of them) extremely close to native implementation (whether it existed).
                      Чего тут реально не хватает, так это возможности раскидать перекрытия базового мультиметода по разным единицам трансляции, т.к. для этого требуется либо перенести компиляцию частично в линк-тайм, либо перенести разрешение перегрузки в ран-тайм. Остальное использование практически никак не ограничивает обычное использование обычных функций, расширяя однако его до возможности позднего связывания некоторых (или всех) аргументов.

                      Добавлено
                      Если UB задокументировано в Стандарте, то её наличие в языке не проблема. Многие реализации доопределяют те или иные аспекты, Стандарт оставляет за ними такое право как раз для непереносимых аспектов исполнительных платформ. Например, разыменование nullptr во многих реализация более чем допустимо, т.к. там лежат таблицы векторов прерываний, например. Программа при этом не будет соответствовать Стандарту, т.к. корректно отработать ей на другой реализации запросто будет невозможным, однако конкретно в этой реализации она будет иметь строго определённое поведение. За эти качества C/C++ и получили свою нишу, которую у них отобрать непросто. Надёжность кода измеряется ...немного другими метриками.
                      Сообщение отредактировано: Qraizer -
                        Цитата Qraizer @
                        Если UB задокументировано в Стандарте, то её наличие в языке не проблема. Многие реализации доопределяют те или иные аспекты, Стандарт оставляет за ними такое право как раз для непереносимых аспектов исполнительных платформ. Например, разыменование nullptr во многих реализация более чем допустимо, т.к. там лежат таблицы векторов прерываний, например. Программа при этом не будет соответствовать Стандарту, т.к. корректно отработать ей на другой реализации запросто будет невозм

                        Не сочти за неуважение :) Но наличие ссылок на возможные UB уничижает понятие "надёжности" в/на 100500 раз. Не нужно больше слов! Есть недетерминированное поведение в ряде случаев - просто в тут забудь про слово "надёжность" желательно надёжно :lol:
                          Qraizer, ты с godbolt разобрался, увидел ссылку мою? Там можно выбрать разные компиляторы (и архитектуры) и ключи разные прописать. Очень удобно.

                          Добавлено
                          И про noexcept согласен с комментарием?

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

                          Нет, не любые. Иногда это как раз прямой путь со стандартными подходами и надежными инструментами :)

                          В данном случае не костылями была бы такая реализация, которая действительно работала бы на уровне синтаксического сахара. Это могла бы быть и библиотека, если бы у C++ были для этого средства. Или если бы данный кейс можно было бы разрулить за счет исключительно метапрограммирования и, например, компайл-тайм рефлексии.
                          1 пользователей читают эту тему (1 гостей и 0 скрытых пользователей)
                          0 пользователей:


                          Рейтинг@Mail.ru
                          [ Script execution time: 0,0541 ]   [ 14 queries used ]   [ Generated: 15.06.25, 00:30 GMT ]