1. C++ / Говнокод #19724

    +8

    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
    45. 45
    template <size_t capacity, bool is_signed>
    class fixed_int
    {	
        // Описание ошибки компиляции в случае использования не поддерживаемой размерности 
        template <int x> struct unsupported_capacity { int i[1/(x-x)]; };
        template <> struct unsupported_capacity<1> {};
        template <> struct unsupported_capacity<2> {};
        template <> struct unsupported_capacity<4> {};
        template <> struct unsupported_capacity<8> {};
    
        // Свойства базовых типов, необходимые для перебора
        template<typename type> struct type_traits;
        template<> struct type_traits <unsigned char> { typedef unsigned char current_type; typedef unsigned short next_type; };
        template<> struct type_traits <unsigned short> { typedef unsigned short current_type; typedef unsigned int next_type; };
        template<> struct type_traits <unsigned int> { typedef unsigned int current_type; typedef unsigned long next_type; };
        template<> struct type_traits <unsigned long> {	typedef unsigned long current_type; typedef unsigned long long next_type; };
        template<> struct type_traits <unsigned long long int> { typedef unsigned long long int current_type;  typedef unsupported_capacity<capacity> next_type; };
        template<> struct type_traits <signed char> { typedef signed char current_type; typedef short next_type; };
        template<> struct type_traits <short> { typedef short current_type; typedef int next_type; };
        template<> struct type_traits <int> { typedef int current_type; typedef long next_type; };
        template<> struct type_traits <long> { typedef long current_type; typedef long long next_type; };
        template<> struct type_traits <long long int> { typedef long long int current_type;  typedef unsupported_capacity<capacity> next_type;};
    
        // Алгоритм выбора типа
        template<typename type, bool> 
        struct type_choice 
        { 
            typedef typename type_traits<type>::current_type std_type; 
        };
        template<typename type> 
        struct type_choice<type, false> 
        { 
            typedef typename type_traits<type>::next_type next_type; 
            typedef typename type_choice<next_type, sizeof(next_type) == capacity>::std_type std_type; 
        };
    
        // Базовый тип для начала подбора
        template <bool is_signed> struct base_type_selector { typedef signed char base_type; };
        template <> struct base_type_selector<false> { typedef unsigned char base_type; };
    
    public:
    
        typedef typename type_choice< typename base_type_selector<is_signed>::base_type, sizeof(base_type_selector<is_signed>::base_type) == capacity >::std_type type;
    
    };

    "Зачем мне нужен stdint.h?
    У меня нет времени, чтобы ебаться с ним!
    Лучше я высру ещё десяток-другой шаблонов!"
    https://habrahabr.ru/post/280542/

    PS,
    Пятая строка - вообще угар.

    Запостил: gost, 31 Марта 2016

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

    • ты бы мог написать что ты думаешь по этому поводу на хабре, там, где была выложена эта статья. Или не мог? Хм...
      Ответить
      • Куда нам, холопам, до сударей достопочтенных, на хабре сидящих?
        Ответить
      • швабре хуй
        Ответить
    • > Менее умные компиляторы <...>, например Qt
      Ответить
      • Когда это qt стал компилятором?
        Ответить
        • есть разве что Qt Quick Compiler. Который не имеет никакого отношения к c++ в принципе ;)
          Ответить
        • Он видимо имел в виду moc или qt creator.
          Ответить
    • почему никто не предложил boost.mpl?
      Ответить
    • Код говно, так как если шорт и инт одинакового размера, будет выбран шорт.
      Ответить
      • Говняность кода не зависит от sizeof({int, short}).
        Ответить
      • какая разница какой из типов одинакового размера будет выбран?
        Ответить
        • А какая разница, мальчик или девочка?
          Ответить
          • Сперва прочитал:
            >А какая реализация, мальчик или девочка?
            Ответить
    • "В своей библиотеке стараюсь писать кроссплатформенный код, где это возможно, по стандарту C++, так что для интегральных типов использую только стандартную «десятку» (signed char, unsigned char, short, unsigned short, int, unsigned int, long, unsigned long, long long, unsigned long long) и никаких виндовых DWORD, __int64 и т.п."

      винды как винды. поэтому и "кроссплатформенно*; (*)поддерживаем только винды."

      тема на самом деле нетривиальная. еще помню как сам в подсознании недели медитировал над бсд-шным "file descriptor is int". потому что после годов braindamage от WinAPI нечто настолько простое и примитивное мозги не принимали.
      Ответить
      • разве в WinAPI хендлер файла не является интом?
        Ответить
        • нет. HANDLE это PVOID это `void *`.

          https://msdn.microsoft.com/en-us/library/windows/desktop/aa363858%28v=vs.85%29.aspx

          https://msdn.microsoft.com/en-us/library/windows/desktop/aa383751%28v=vs.85%29.aspx
          Ответить
          • > HANDLE это PVOID это `void *`
            А разве это плохо?
            Ответить
            • HANDLE сам по себе не плох.

              плохо то что винды используют кучи typedef'ов для каждой всевозможной мелочи, и большинство этих тайпдефов начинаются с `H` как бы намекая что они тоже handle. грабли в том что не все из этих хандлов есть HANDLE'ы. и это настоящие грабли на которые народ часто наступает. для "решения" этой "проблемы" в windows.h есть "STRICT" дефайн который из `void *` делает `unique_dummy_struct *` что бы все хандлы были разных типов, но это помогает слабо потому что код плавно и неизбежно обрастает конверсиями хандлов, и мы опять там где начали.

              ЗЫ пример: HFILE.
              Ответить
              • зачем конвертировать хендлы?
                Ответить
                • чтобы писать код, который упадет в слелующей версии винды и можно будет орать что микрософт говно
                  Ответить
                  • не ну интересно
                    можно как в пост, взять хендл мяса и вслух объявить его спаржей, после чего жрать как спаржу
                    только вот бы пример более реальный
                    Ответить
                    • да ни за чем это не надо

                      приводить друг к другу типы, которые официально не приводятся это говнокод

                      https://en.wikipedia.org/wiki/Opaque_data_type
                      Ответить
                  • хаха. очень смешно.

                    я еще не разу не видел куска кода 100% портабельного кода для виндов.

                    в прошлом тупо все примеры изо всех версий msdev'а (когда он еще msdev'ом назывался) - сканировал на предмет как правильно писать. и бля те же примеры часто уже на другой версии msdev'а не собирались, не говоря уже о том что бы работали на другой версии виндов без проблемно.

                    не говоря о выньапи - даже шарп не исключение.
                    Ответить
                • потому что кучи апишных функций берут абстрактный хэндл как аргумент.

                  класические примеры говно-источников этого маразма это WaitSingleObject()/этц и SelectObject().

                  если ты пытаешься в своем коде хотя бы какой-то порядок навести, что бы отличать десятки разных типов хэндлов (потому что бля указывают на разные типы объектов) то желательно пользоватся правильными типами. как ни крути - грабли.
                  Ответить
                  • Кажется, теперь понял, о чём речь.

                    Некоторые функции WinAPI принимают в качестве одного аргумента дескриптор из некоторого множества типов, например, {HFILE, HWND, HSOMETHING}, а в сраной сишке нет возможности это описать вменяемым способом. Из ситуации есть несколько выходов:
                    1. «Перегрузка» функций. Т. е. плодить функции WaitSingleObjectHFILE, WaitSingleObjectHWND, WaitSingleObjectHSOMETHING etc.

                    2. Оборачивать дескриптор в union. Например, создать тип HSOMESETOFTYPES, являющийся union'ом из HFILE, HWND, HSOMETHING.

                    3. Конвертировать типы в какой-нибудь базовый вроде HANDLE.

                    Я правильно понял?
                    Ответить
                    • стоп!
                      кастить вверхз и вниз можно, а кастить вбок нельзя.
                      Kill(HANDLE handle);
                      
                      HPIDAR pidar;
                      HPIDAR2 pidar2;
                      Kill(HPIDAR)pidar)'; // OK, потому что так написано в документации
                      
                      pidar2 = (HANDLE)pidar; // не ок
                      Ответить
                    • > Я правильно понял?

                      Да.
                      Ответить
              • А часто ли требуется разыменовывать хэндлы, чтобы посмотреть, на что они указывают? Не проще ли считать, что это тупо некий UID?
                Ответить
                • блин
                  люди, вы чего??
                  хендл это OPAQUE TYPE! Вам вообще никто не гарантирует что там внутри
                  Ответить
                • потому что разные хэндлы указывают на разные типы объектов и разные типы объектов манипулируются разными функциями апи.
                  Ответить
                • Ну типа хочется чтобы были HFILE, HEVENT, HSOCKET и т.п. И все их можно было кастовать в HANDLE (чтобы передать обобщённой функции типа WaitForMultipleObject), но нельзя было смешивать между собой и апкастить из HANDLE без явной проверки.

                  А что у них внутри - всем насрать.
                  Ответить

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