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

    +2

    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
    46. 46
    47. 47
    48. 48
    49. 49
    50. 50
    51. 51
    52. 52
    53. 53
    54. 54
    55. 55
    56. 56
    57. 57
    58. 58
    59. 59
    60. 60
    61. 61
    62. 62
    63. 63
    64. 64
    65. 65
    66. 66
    67. 67
    68. 68
    69. 69
    70. 70
    71. 71
    72. 72
    73. 73
    74. 74
    75. 75
    76. 76
    77. 77
    78. 78
    79. 79
    80. 80
    81. 81
    82. 82
    83. 83
    84. 84
    85. 85
    86. 86
    87. 87
    88. 88
    89. 89
    90. 90
    91. 91
    92. 92
    93. 93
    94. 94
    95. 95
    96. 96
    97. 97
    98. 98
    #include <array>
    #include <iostream>
    #include <string_view>
    #include <type_traits>
    
    std::string_view getMaxMargin();
    
    template<int bit_num>
    struct flag {
        friend constexpr int adl_flag(flag<bit_num>);
    };
    
    template<int bit_num>
    struct writer {
        friend constexpr int adl_flag(flag<bit_num>)
        {
            return bit_num;
        }
    
        static constexpr int value = bit_num;
    };
    
    template<int bit_num, int = adl_flag(flag<bit_num>{})>
    constexpr bool is_flag_set(int, flag<bit_num>)
    {
        return bit_num >= 0;
    }
    
    template<int bit_num>
    constexpr bool is_flag_set(float, flag<bit_num>)
    {
        return false;
    }
    
    template<size_t number, size_t bit_num>
    constexpr bool get_bit()
    {
        return (number & (1 << bit_num)) != 0;
    }
    
    #define flags_to_size()                     \
         ((is_flag_set<0>(0, flag<0>{}) << 0)   \
        | (is_flag_set<1>(0, flag<1>{}) << 1)   \
        | (is_flag_set<2>(0, flag<2>{}) << 2)   \
        | (is_flag_set<3>(0, flag<3>{}) << 3))
    
    template<bool test, typename T_true, typename T_false>
    struct meta_if {
        using type = T_true;
    };
    
    template<typename T_true, typename T_false>
    struct meta_if<false, T_true, T_false> {
        using type = T_false;
    };
    
    template<bool test, typename T_true, typename T_false>
    using meta_if_t = typename meta_if<test, T_true, T_false>::type;
    
    template<
        size_t desired_size,
        int = (0 +
               sizeof(meta_if_t<get_bit<desired_size, 0>(), writer<0>, int>) +
               sizeof(meta_if_t<get_bit<desired_size, 1>(), writer<1>, int>) +
               sizeof(meta_if_t<get_bit<desired_size, 2>(), writer<2>, int>) +
               sizeof(meta_if_t<get_bit<desired_size, 3>(), writer<3>, int>)
        )
    >
    constexpr size_t f()
    {
        return desired_size;
    }
    
    int main()
    {
        constexpr size_t a = f<1>();
        constexpr size_t b = f<6>();
        std::cout << "Max margin size: " << getMaxMargin().size() << std::endl;
    }
    
    constexpr size_t MARGIN_SIZE = flags_to_size();
    constexpr char MARGIN_CHAR = 'x';
    
    template<typename T, T... Args>
    constexpr auto getMarginStorageImpl(std::integer_sequence<T, Args...>)
    {
        return std::array<char, sizeof...(Args)>{(static_cast<void>(Args), MARGIN_CHAR)...};
    }
    constexpr auto getMarginStorage()
    {
        return getMarginStorageImpl(std::make_integer_sequence<int, MARGIN_SIZE>());
    }
    constexpr static auto marginStorage = getMarginStorage();;
    
    std::string_view getMaxMargin()
    {
        return std::string_view(marginStorage.data(), MARGIN_SIZE);
    }

    "Интересно, можно ли насфиначить такой шаблон, чтобы в пределах TU сгенерированные литералы были слайсами одного статического массива, длина которого выводилась бы автоматически."

    Запостил: PolinaAksenova, 25 Марта 2021

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

    • Сделано на основе чёрной магии из https://b.atch.se/posts/non-constant-constant-expressions/, работает на свежих версиях MSVC, gcc и clang. На UB не проверялось, т.к. лень.

      Как видно, реализация поддерживает все размеры до 15-ти байт. Задачу расширения на 64 бита оставим на совести читателей.
      Ответить
      • Небольшая поправочка, конечно:
        constexpr std::string_view f()
        {
            return getMaxMargin().substr(0, desired_size);
        }
        
        int main()
        {
            auto margin_a = f<2>();
            auto margin_b = f<11>();
            std::cout << "Max margin size: " << getMaxMargin().size() << std::endl;
            std::cout << "Margin_a: " << margin_a << std::endl;
            std::cout << "Margin_b: " << margin_b << std::endl;
        }
        Ответить
    • > int = 0 + ...

      Лол, у аргументов с дефолтом можно имя не писать?
      Ответить
    • Какой хардкор )))
      Ответить
    • Добрый день.

      Этот оффтоп сгенерирован автоматически.

      Индекс оффтопов: https://index.gcode.space/.
      Зеркала Говнокода и полезные ресурсы:
      * https://govnokod.xyz/ (альтернативный Говнокод)
      * https://gcode.space/ (read-only зеркало Говнокода)
      * https://t.me/GovnokodBot (Говнокод-бот в «Telegram»)
      * https://t.me/GovnokodChannel (Тематический канал в «Telegram»)
      * https://vorec.space/ (глоссарий Говнокода)
      * https://app.element.io/#/room/#govnokod:matrix.org (резервный чат)
      Ответить

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