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

    +4

    1. 1
    2. 2
    3. 3
    4. 4
    5. 5
    6. 6
    7. 7
    8. 8
    9. 9
    #include <iostream>
    #include <string>
    #include <string_view>
    
    int main() {
      std::string s = "Hellooooooooooooooo ";
      std::string_view sv = s + "World\n";
      std::cout << sv;
    }

    https://alexgaynor.net/2019/apr/21/modern-c++-wont-save-us/
    What's happening here is that s + "World\n" allocates a new std::string, and then is converted to a std::string_view. At this point the temporary std::string is freed, but sv still points at the memory that used to be owned by it. Any future use of sv is a use-after-free vulnerability. Oops! C++ lacks the facilities for the compiler to be aware that sv captures a reference to something where the reference lives longer than the referent. The same issue impacts std::span, also an extremely modern C++ type.

    j123123, 24 Апреля 2019

    Комментарии (83)
  2. C++ / Говнокод #25562

    +2

    1. 1
    2. 2
    3. 3
    4. 4
    5. 5
    6. 6
    7. 7
    8. 8
    // https://github.com/WebKit/webkit/blob/e0e7e8f907f4c01c723374e8230a63d46e89e6a0/Source/WebCore/platform/graphics/filters/FEComposite.cpp#L98
    
    static unsigned char clampByte(int c)
    {
        unsigned char buff[] = { static_cast<unsigned char>(c), 255, 0 };
        unsigned uc = static_cast<unsigned>(c);
        return buff[!!(uc & ~0xff) + !!(uc & ~(~0u >> 1))];
    }

    j123123, 22 Апреля 2019

    Комментарии (23)
  3. C++ / Говнокод #25558

    +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
    https://habr.com/ru/article/448466/
    
    */
    А последние пару лет набирает популярность boost.hana. Это boost.fusion,
    но с constexpr'ом и лямбдами. Автор hana, Луис Дионе (Louis Dionne),
    используя на полную мощь все возможности новых стандартов, в некотором
    смысле очеловечил метапрограммирование. С помощью hana всяческие
    манипуляции с типами, их кортежами, отображениями, а также компайл- и
    рантайм-работа с ними обрели практически человеческое лицо и читаемый
    вид. Ну, с поправкой на синтаксис C++, разумеется. Вот, например, как выглядит
    универсальный сериализатор структур, написанный с помощью hana:
    */
    
    // 1. Give introspection capabilities to 'Person'
    struct Person {
      BOOST_HANA_DEFINE_STRUCT(Person,
        (std::string, name),
        (int, age)
      );
    };
    // 2. Write a generic serializer (bear with std::ostream for the example)
    auto serialize = [](std::ostream& os, auto const& object) {
      hana::for_each(hana::members(object), [&](auto member) {
        os << member << std::endl;
      });
    };
    // 3. Use it
    Person john{"John", 30};
    serialize(std::cout, john);
    
    /*
    Ну да, структуры приходится описывать особым образом. А кому сейчас легко?
    И тут хочется также отметить библиотеку tinyrefl за авторством Manu Sánchez
    (Мануэля Санчеса). Довольно неплохая попытка принести в мир C++-разработки
    статическую рефлексию без расширения компилятора. Для своей работы библиотека
    требует стороннюю утилиту (cppast), но зато предоставляет довольно удобный доступ
    к информации о структурах, которую можно использовать в процессе разработки
    программы. Преимущество этой библиотеки (по сравнению с другими) в том, что для
    работы с ней не надо использовать «птичий язык», а элементы структур (как и сами
    структуры) можно произвольным образом атрибутировать прямо в исходном коде:
    */
    
    struct [[serializable]] Person {
        std::string name;
        int age;
    };
    template<typename Class>
    auto serialize(std::ostream& os, Class&& object) -> std::enable_if_t<
            tinyrefl::has_metadata<std::decay_t<Class>>() &&
            tinyrefl::has_attribute<std::decay_t<Class>>("interesting"),
        std::ostream&>
    {
        tinyrefl::visit_member_variables(object, [&os](const auto& /* name */, const auto& var) {
            os << var << std::endl;
        });
        return equal;
    }
    
    /*
    Таких примеров можно привести ещё много (или найти на гитхабе или гитлабе).
    Объединяет все эти библиотеки и инструменты одна особенность: значительно
    облегчая жизнь своим пользователям, они имеют такую реализацию, что остаётся
    лишь предполагать, какое количество страданий испытали их разработчики. Достаточно
    заглянуть в реализацию, увидеть забор из ifdef'ов и угловых скобок — и всё понятно.
    Нередко эти реализации делаются на грани возможностей компиляторов. workaround'ы
    банальных ошибок (или особенностей реализации языка конкретной версии конкретного
    компилятора с конкретными флагами) здорово раздувают их код. Желание поддерживать
    несколько стандартов сразу заставляет придумывать зубодробильные конструкции.
    Безусловно, простая попытка реализовать что-нибудь подобное здорово поднимает уровень
    владения языком (иногда — и самооценку). Но в какой-то момент, после многочасовой возни
    с очередной ошибкой, или непроходящим тестом, или крэшем компилятора руки опускаются,
    хочется плюнуть и бросить, ибо силы бороться иссякают.
    */

    Именно поэтому я за гомоиконность

    j123123, 21 Апреля 2019

    Комментарии (50)
  4. C++ / Говнокод #25547

    +1

    1. 1
    2. 2
    #include <type_traits>
    int main() { return std::is_assignable_v<int, int>; }

    --> 0

    WTF?

    Elvenfighter, 17 Апреля 2019

    Комментарии (47)
  5. C++ / Говнокод #25520

    +1

    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
    #include <iostream>
    #include <functional>
    #include <array>
    #include <iterator>
    
    template <class T>
    class Filter : public std::iterator<
                     std::input_iterator_tag,
                     typename std::iterator_traits<T>::value_type,
                     typename std::iterator_traits<T>::difference_type,
                     typename std::iterator_traits<T>::pointer,
                     typename std::iterator_traits<T>::reference
                   >
    {
    private:
      typedef typename std::iterator_traits<T>::value_type value_type;
      std::function<bool(value_type)> m_predicate;
      T m_begin, m_end;
      value_type m_current;
    
    public:
      Filter(T t_begin, T t_end, std::function<bool(value_type)> t_predicate)
        : m_begin(t_begin), m_end(t_end), m_predicate(t_predicate)
      {
      }
      
      Filter<T>& begin()
      {
        return ++*this;
      }
      
      Filter<T>& end()
      {
        return *this;
      }
      
      value_type operator* ()
      {
        return m_current;
      }
      
      Filter<T>& operator++ ()
      {
        do {
          m_current = *m_begin;
          ++m_begin;
        } while (m_begin != m_end && !m_predicate(m_current));
        return *this;
      }
      
      
      bool operator!= (Filter<T>& t_right)
      {
        return m_begin != t_right.m_end;
      }
    };
    
    
    int main()
    {
      std::array<int, 10> arr{ {4, 35, 0, 23, 0, 0, 5} };
      for (auto i : Filter<typename std::array<int,10>::iterator>(arr.begin(), arr.end(), [](int x){return x != 0;})) {
        std::cout << i << " ";
      }
    }

    Lemming, 07 Апреля 2019

    Комментарии (63)
  6. C++ / Говнокод #25498

    +1

    1. 1
    https://en.cppreference.com/w/cpp/language/lambda

    > Explanation
    > > <tparams>
    > Like in a template declaration, the template parameter list may be followed by an optional requires-clause, which specifies the constraints on the template arguments.
    > optional requires-clause
    небязательные обязательные пункты.

    Переводил почти час.

    OlegUP, 02 Апреля 2019

    Комментарии (26)
  7. C++ / Говнокод #25490

    +3

    1. 1
    2. 2
    3. 3
    //  https://stackoverflow.com/questions/313970/how-to-convert-stdstring-to-lower-case?__=1746193182#
    
    std::transform(data.begin(), data.end(), data.begin(), ::tolower);

    Какой багор )))

    BOKCEJIbHblu_nemyx, 31 Марта 2019

    Комментарии (21)
  8. C++ / Говнокод #25466

    +4

    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
    #include <inttypes.h>
    
    auto a(auto b) __attribute__ ((noinline));
    
    auto a(auto b)
    {
        return b*1.5;
    }
    
    double test1(double in)
    {
      return a(in);
    }
    
    uint64_t test2(uint64_t in)
    {
      return a(in);
    }
    
    
    /*
    https://godbolt.org/z/6ZQAnv
    
    auto a<double>(double):
            mulsd   xmm0, QWORD PTR .LC0[rip]
            ret
    test1(double):
            jmp     auto a<double>(double)
    auto a<unsigned long>(unsigned long):
            test    rdi, rdi
            js      .L5
            pxor    xmm0, xmm0
            cvtsi2sd        xmm0, rdi
            mulsd   xmm0, QWORD PTR .LC0[rip] # хули ты мне плавучего питуха в xmm0 возвращаешь?
            ret
    .L5:
            mov     rax, rdi
            and     edi, 1
            pxor    xmm0, xmm0
            shr     rax
            or      rax, rdi
            cvtsi2sd        xmm0, rax
            addsd   xmm0, xmm0
            mulsd   xmm0, QWORD PTR .LC0[rip]
            ret
    test2(unsigned long):
            sub     rsp, 8
            call    auto a<unsigned long>(unsigned long)
            movsd   xmm1, QWORD PTR .LC1[rip]
            comisd  xmm0, xmm1
            jnb     .L8
            cvttsd2si       rax, xmm0 # ну нахуй тут надо double в uint64_t конвертить
            add     rsp, 8 # почему это не делается в auto a<unsigned long>(unsigned long)
            ret
    .L8:
            subsd   xmm0, xmm1
            add     rsp, 8
            cvttsd2si       rax, xmm0
            btc     rax, 63
            ret
    .LC0:
            .long   0
            .long   1073217536
    .LC1:
            .long   0
            .long   1138753536
    
    */

    концепты-хуепты

    j123123, 23 Марта 2019

    Комментарии (28)
  9. C++ / Говнокод #25454

    +1

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    template<typename T>
    class IsClassT {
      private:
        typedef char One;
        typedef struct { char a[2]; } Two;
        template<typename C> static One test(int C::*);
        // Will be chosen if T is anything except a class.
        template<typename C> static Two test(...);
      public:
        enum { Yes = sizeof(IsClassT<T>::test<T>(0)) == 1 };
        enum { No = !Yes };
    };

    Как эта поебота работает?
    Что такое "int C::*"?

    A3APTHblu_nemyx, 19 Марта 2019

    Комментарии (133)
  10. C++ / Говнокод #25445

    +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
    #include <type_traits>
    
    struct Foo {
      void bar(int) const & {}
    };
    
    int main() {    
      using MethodPtr = decltype(&Foo::bar);
      const MethodPtr arr[] = { &Foo::bar };
      auto *ptr = &arr;
      auto &ref = ptr;
    
      static_assert(std::is_same_v<decltype(ref), void (Foo::* const (*&)[1])(int) const &>);
    }

    Магия указателей возведенная в степень магии массивов в степени магии ссылок.

    https://wandbox.org/permlink/8DygQ6oocrEY1K1M

    Elvenfighter, 11 Марта 2019

    Комментарии (23)