1. Си / Говнокод #25202

    0

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    15. 15
    16. 16
    17. 17
    18. 18
    19. 19
    20. 20
    21. 21
    22. 22
    23. 23
    24. 24
    25. 25
    26. 26
    27. 27
    28. 28
    29. 29
    30. 30
    31. 31
    32. 32
    33. 33
    34. 34
    35. 35
    36. 36
    37. 37
    38. 38
    39. 39
    40. 40
    41. 41
    42. 42
    43. 43
    44. 44
    enum crap
    {
        shit = 0,
        fuck,
        dick,
        ass,
        turd,
        fart,
    };
    
    static char *crap_to_str(int crap)
    {
        switch (crap)
        {
            case shit:
            {
                return "shit";
            }
            case fuck:
            {
                return "fuck";
            }
            case dick:
            {
                return "dick";
            }
            case ass:
            {
                return "ass";
            }
            case turd:
            {
                return "turd";
            }
            case fart:
            {
                return "fart";
            }
            default:
            {
                return "!!!UNKNOWN CRAP!!!";
            }
        }
    }

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

    Запостил: j123123, 18 Декабря 2018

    Комментарии (45) RSS

    • https://stackoverflow.com/questions/240353/ - для сишного препроцессора такая хрень есть, из которой через какую-то там препроцессорную жопу можно и структуры и функцию со switch нагенерить, но мы исходим из предположения, что у нас уже определены готовые структуры, и переделывать это в понос из сишного препроцессора мы не хотим
      Ответить
      • Через RTTI можно узнать тип енума, но не название значения:

        https://ideone.com/I5vW1M
        Ответить
        • Ещё можно занеймспейсить, но будет та же фигня:
          #include <iostream>
          #include <typeinfo>
          
          enum class crap
          {
              shit = 0,
              fuck,
              dick,
              ass,
              turd,
              fart,
          };
          
          int main() {
              crap x = crap::dick;
              std::cout << typeid(x).name() << std::endl;
              return 0;
          }
          Ответить
    • Поэтому я за Javascript
      const crap = Object.freeze(
      {
          shit: 0,
          fuck: 1,
          dick: 2,
          ass: 3,
          turd: 4,
          fart: 5
      });
      
      const obj_to_str = obj => val => {
        const arr = Object.entries(obj).find(([key, value]) => value === val)
        return arr? arr.shift(): '!!!UNKNOWN CRAP!!!'}
      
      const crap_to_str = obj_to_str(crap)
      
      console.log(crap_to_str(crap.fuck)) // 'fuck'
      console.log(crap_to_str(crap.faggot)) // '!!!UNKNOWN CRAP!!!'
      Ответить
      • Если определить метод toString(), тогда можно будет просто console.log(crap.fuck).
        Ответить
        • Если я правильно понял автора, он хочет выводить коды произвольного enum'a.
          Если я правильно понял тебя, то toString() придется определять для всех enum'ов.
          Ответить
    • А что, если сделать не препроцессор, а постпроцессор? Из отладочной информации объектного файла (dwarf, stabs) можно поймать что-нибудь полезное?

      https://sourceware.org/gdb/current/onlinedocs/stabs.html#Enumerations

      http://git.dwarfstd.org/?p=dwarf-doc.git;a=blob;f=dwarf5/latexdoc/typeentries.tex;hb=HEAD#l1594
      Ответить
      • Идея такая:
        1. Есть заголовочный файл с енумами.
        2. Инклюдишь его в какой-нибудь файл.
        3. Компилируешь этот файл с отладочной информацией.
        4. Пропускаешь объектный файл через постпроцессор, который вытаскивает отладочные записи для енумов, и генерирует из них функцию или базу данных, переводящую числа в наименования значений.
        5. ?????
        6. Выгода.
        Ответить
    • Тут вполне предостаточно сишного препроцессора:
      #include <stdio.h>
      
      #define CAT_(a, ...) a ## __VA_ARGS__
      #define CAT(...) CAT_(__VA_ARGS__)
      
      #define EAT(...)
      #define EXPAND(...) __VA_ARGS__
      #define IIF(c) CAT(IIF_, c)
      #define IIF_1(...) __VA_ARGS__ EAT
      #define IIF_0(...) EXPAND
      
      #define COMPL(x) CAT(COMPL_, x)
      #define COMPL_1 0
      #define COMPL_0 1
      
      #define CHECK_N(x, n, ...) n
      #define CHECK(...) CHECK_(__VA_ARGS__)
      #define CHECK_(...) CHECK_N(__VA_ARGS__, 0)
      #define PROBE(x) x, 1
      
      #define IS_EMPTY(x) BOOL(CHECK(CAT(IS_EMPTY_, x)()))
      #define IS_EMPTY_()   PROBE(~)
      
      #define NOT(x) CHECK(CAT(NOT_, x))
      #define NOT_0 PROBE(~)
      #define BOOL(x) COMPL(NOT(x))
      
      #define IF(c) IIF(BOOL(c))
      #define UNLESS(c) IF(c)()
      
      #define EMPTY()
      #define DEFER(id) id EMPTY()
      #define OBSTRUCT(id) id DEFER(EMPTY)()
      
      #define  EVAL(...) EVAL1(EVAL1(EVAL1(EVAL1(__VA_ARGS__))))
      #define EVAL1(...) EVAL2(EVAL2(EVAL2(EVAL2(__VA_ARGS__))))
      #define EVAL2(...) EVAL3(EVAL3(EVAL3(EVAL3(__VA_ARGS__))))
      #define EVAL3(...) EVAL4(EVAL4(EVAL4(EVAL4(__VA_ARGS__))))
      #define EVAL4(...) EVAL5(EVAL5(EVAL5(EVAL5(__VA_ARGS__))))
      #define EVAL5(...) __VA_ARGS__
      
      #define FOREACH(macro, x, ...) \
        UNLESS(IS_EMPTY(x))( \
          macro(x) \
          OBSTRUCT(FOREACH_INDIRECT)()(macro, __VA_ARGS__) \
        )
      
      #define FOREACH_INDIRECT(...) FOREACH
      
      #define QUOTE(...) QUOTE_(__VA_ARGS__)
      #define QUOTE_(...) #__VA_ARGS__
      
      #define ENUM_ARR_ELEM(x) , QUOTE(x)
      #define ENUM(tag, first, ...) \
          enum tag {first, __VA_ARGS__}; \
          char *CAT(tag, _names)[] = {QUOTE(first)EVAL(FOREACH(ENUM_ARR_ELEM, __VA_ARGS__))}; \
          static char *CAT(tag, _to_str) (int x) \
          { \
              return x > sizeof(CAT(tag, _names)) / sizeof(char*) ? QUOTE(!!!UNKNOWN tag!!!) : CAT(tag, _names)[x]; \
          }
      
      ENUM(crap,
          shit,
          fuck,
          dick,
          ass,
          turd,
          fart
      )
      
      int main()
      {
          puts(crap_to_str(shit));
          puts(crap_to_str(666));
          return 0;
      }
      https://ideone.com/3Ehv01
      Ответить
      • Красиво. Но ведь бывают перечисления с дырками:
        enum crap
        {
            shit = 0,
            fuck,
            dick = 42,
            ass,
            turd = 265,
            fart,
        };

        Как с такими поступать?
        Ответить
    • На луа переведи
      Ответить
    • Насколько я знаю, из готового определения структуры — только какой-нибудь еблей с парсингом определений и генерацией исходников прямо во время конпелирования. Интроспекцию-то не завезли.
      Ответить
      • Можно джава-стайл енумы запилить (указатель на статик вместо числа).
        Ответить
        • Надо их еще суметь сгенерировать из обычных готовых сишных энумов, а это ни в плюсах ни в сишке никак не сделать по-нормальному. Только писать код который читает и парсит код с этими самыми структурами и генерирует функции на основе него. И это при всем том количестве всевозможной хуйни, которую в последнем крестопарашном стандарте добавили стандартизаторы.
          Ответить
    • в джаве и котлине самые охуенные энамы. все остальное поебень на постном масле.
      Ответить
      • В котлине есть sealed классы
        Это такие енумы у которых сосут все остальные енумы
        Ответить
      • В нормальных языках есть алгебраические типы данных. Всё остальное — «поебень на постном масле».
        Ответить
        • В нормальных языках есть абстрактные инструменты(term rewriting system), которыми ты можешь построить любые типы данных. Всё остальное — «поебень на постном масле».

          Abstract reduction system, (abbreviated ARS) is the most general (unidimensional) notion about specifying a set of objects and rules that can be applied to transform them.
          Ответить
    • Q_ENUM
      Ответить
    • У нас эту проблему решает protoc.
      Ответить
    • Как правильно сказал роман это может делать протобуфный тул

      Доречи еще всякие тулы из схем wsdl генерят прокси классы
      Ответить
    • DSL себе напиши, ты же всем это рекомендуешь.
      Желательно описывать всё в Axiom, чтобы гомоиконы и котогенерация.
      Ответить
      • А я так и делаю - пишу код, который принтф-ами в цикле сначала нахерачивает енумы, а потом нахерачивает функции.
        Ответить
        • poor man's метапрограммирование
          Ответить
          • В плюсах-то для этого вообще нет решения. Так что плюсовое метапрограммирование даже хуже
            Ответить
            • редко в каком мейнстримовом языке это есть

              обычно берут кодоргенерацию.
              Ответить
        • Надеюсь, ты делаешь это из «PHP»?
          Ответить
      • > Желательно описывать всё в Axiom, чтобы гомоиконы и котогенерация.

        Не, лучше в Metamath http://us.metamath.org/mpeuni/mmset.html
        Чтоб https://en.wikipedia.org/wiki/Rewriting
        Ответить
    • Вот завезут рефлексию -- можно будет. А сейчас -- не нужно!
      Ответить
    • Как вариант:
      namespace detail::crap {
        constexpr auto shitstore = "shit\0fuck\0dick\0ass\0turd\0fart";
      }
      
      enum class crap : std::ptrdiff_t {
        shit = 0,
        fuck = shit + 5,
        dick = fuck + 5,
        ass = dick + 5,
        turd = ass + 4,
        fart = turd + 5,
      };
      
      constexpr auto crap_to_str(crap c) { return &detail::crap::shitstore[static_cast<std::underlying_type_t<crap>>(c)]; }


      https://wandbox.org/permlink/QGryioh963FK4n3c
      Ответить
      • shit = 0,
          fuck = shit + 5,
          dick = fuck + 5,
          ass = dick + 5,
          turd = ass + 4,
          fart = turd + 5,


        О даааа, считать буковки, как настоящие вконтактовские олимпиадные программисты https://govnokod.ru/24447
        Ответить
      • #include <iostream>
        #include <string_view>
        #include <cstdint>
        
        namespace detail::crap {
          constexpr auto shitstore = "shit\0fuck\0dick\0ass\0turd\0fart";
        }
        
        
        std::ptrdiff_t constexpr length(const char* str)
        {
            return *str ? 1 + length(str + 1) : 0;
        }
        
        enum class crap : std::ptrdiff_t {
          shit = 0,
          fuck = shit + length(detail::crap::shitstore + shit) + 1,
          dick = fuck + length(detail::crap::shitstore + fuck) + 1,
          ass = dick + length(detail::crap::shitstore + dick) + 1,
          turd = ass + length(detail::crap::shitstore + ass) + 1,
          fart = turd + length(detail::crap::shitstore + turd) + 1,
        };
        
        constexpr auto crap_to_str(crap c) { return &detail::crap::shitstore[static_cast<std::underlying_type_t<crap>>(c)]; }
        
        int main() {
          const auto c = crap::turd;
          std::cout << "today's crap is: " << crap_to_str(c) << '\n'; 
        }


        Пописал на плюсах - как говна поел. https://wandbox.org/permlink/WnrOCbjzOqYmsyxm
        Ответить
        • Проверим:
          ☑ Неймс-пейсы.
          ☑ Слово «class».
          ☑ Перегруженные опера-торы.
          ☑ Констэкспры.
          ☑ Крестошоблоны.
          ☑ Крестокасты.
          ☑ Вывод типов.

          И всё-таки остаётся ощущение, что чего-то не хватает. Может быть, онанимных замыканий?
          Ответить
          • Приправим немного препроцессором
            #include <iostream>
            #include <string_view>
            
            #define GAY(x) ((x) + length(detail::crap::shitstore + (x)) + 1)
            
            namespace detail::crap {
              constexpr auto shitstore = "shit\0fuck\0dick\0ass\0turd\0fart";
            }
            
            std::ptrdiff_t constexpr length(const char* str)
            {
                return *str ? 1 + length(str + 1) : 0;
            }
            
            enum class crap : std::ptrdiff_t {
              shit = 0,
              fuck = GAY(shit),
              dick = GAY(fuck),
              ass = GAY(dick),
              turd = GAY(ass),
              fart = GAY(turd),
            };
            
            constexpr auto crap_to_str(crap c) { return &detail::crap::shitstore[static_cast<std::underlying_type_t<crap>>(c)]; }
            
            int main() {
              const auto c = crap::turd;
              std::cout << "today's crap is: " << crap_to_str(c) << '\n'; 
            }
            Ответить
            • Не хочу мокросы. Хочу больше констэкспров.
              Ответить
              • https://wandbox.org/permlink/Kpd1pjr4SVOWKH5l пока вот держи улучшенную версию на мокросах
                Ответить
    • RTTI:
      {$mode objfpc}
      {$apptype console}
      {$M+}
      
      type
          TRoosters = (GoldenRooster, Junglefowl, FightingCock, Fjalarr, Gullinkambi, GallicRooster, You);
      
      Var
          s: string;
      
      begin
         WriteStr(s, FightingCock);
         Writeln(s)
      end.


      https://ideone.com/wH1KrY

      Именно поэтому я за Фрипаскаль.
      Ответить
      • Пытался реализовать самостоятельно, не применяя вызов WriteStr. Оказывается, RTTI сохраняется только для свойств классов, для скалярных переменных RTTI не записывается. Поэтому для получения массива названий енумов нужно оборачивать свойство в класс:
        {$mode objfpc}
        {$M+}
        
        uses typinfo;
        
        type
            TRoosters = (GoldenRooster, Junglefowl, FightingCock, Fjalarr, Gullinkambi, GallicRooster, You);
        
            TTestPituh = class(TObject)
            private  
                TestField: TRoosters;
            published
                property TestProp: TRoosters read TestField write TestField;
            end;
        
        function GetRoosterName(x: TRoosters): string;
            Var
                O : TTestPituh;
            begin
                O  := TTestPituh.Create;
                GetRoosterName := GetEnumName(GetPropInfo(O,'TestProp')^.PropType, Ord(x));
                O.Destroy
            end;
        
        begin
            Writeln(GetRoosterName(FightingCock))
        end.


        https://ideone.com/FJa8z4
        Ответить
        • Оказывается, инстанс не нужен. И можно даже так:
          {$mode objfpc}
          {$modeswitch typehelpers} 
          {$M+}
          
          uses typinfo;
          
          type
              TRoosters = (GoldenRooster, Junglefowl, FightingCock, Fjalarr, Gullinkambi, GallicRooster, You);
          
              TTestPituh = class(TObject)
              private  
                  TestField: TRoosters;
              published
                  property TestProp: TRoosters read TestField write TestField;
              end;
          
              TRoostersHelper = type helper for TRoosters
              public
                  function GetRoosterName: string;
              end;
           
          function TRoostersHelper.GetRoosterName: string;
              begin
                  GetRoosterName := GetEnumName(GetPropInfo(TTestPituh,'TestProp')^.PropType, LongInt(self))
              end;
          
          begin
              Writeln(FightingCock.GetRoosterName)
          end.


          https://ideone.com/irFUNw
          Ответить
          • JS-Style:
            {$mode objfpc}
            {$modeswitch typehelpers} 
            
            type
                TRoosters = (GoldenRooster, Junglefowl, FightingCock, Fjalarr, Gullinkambi, GallicRooster, You);
            
                TRoostersHelper = type helper for TRoosters
                public
                    function toString: string;
                end;
             
            function TRoostersHelper.toString: string;
                begin
                    WriteStr(Result, self)
                end;
            
            begin
                Writeln(FightingCock.toString)
            end.


            https://ideone.com/5Gb8L6
            Ответить
    • * g o a t s e x * g o a t s e x * g o a t s e x *  
       g                                               g  
       o /     \             \            /    \       o  
       a|       |             \          |      |      a  
       t|       `.             |         |       :     t  
       s`        |             |        \|       |     s  
       e \       | /       /  \\\   --__ \\       :    e  
       x  \      \/   _--~~          ~--__| \     |    x  
       *   \      \_-~                    ~-_\    |    *  
       g    \_     \        _.--------.______\|   |    g  
       o      \     \______// _ ___ _ (_(__>  \   |    o  
       a       \   .  C ___)  ______ (_(____>  |  /    a  
       t       /\ |   C ____)/      \ (_____>  |_/     t  
       s      / /\|   C_____)       |  (___>   /  \    s  
       e     |   (   _C_____)\______/  // _/ /     \   e  
       x     |    \  |__   \\_________// (__/       |  x  
       *    | \    \____)   `----   --'             |  *  
       g    |  \_          ___\       /_          _/ | g  
       o   |              /    |     |  \            | o  
       a   |             |    /       \  \           | a  
       t   |          / /    |         |  \           |t  
       s   |         / /      \__/\___/    |          |s  
       e  |         / /        |    |       |         |e  
       x  |          |         |    |       |         |x  
       * g o a t s e x * g o a t s e x * g o a t s e x *
      Ответить

    Добавить комментарий