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

    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
    // Приведение численного типа к структуре с битовыми полями
    template <class STRUCT_T, typename T>
    STRUCT_T struct_cast(const T n)
    {
        static_assert(std::is_integral<T>::value, "Integral type required as T");
        static_assert(std::is_class<STRUCT_T>::value, "class or struct type required as STRUCT_T");
        static_assert(sizeof(T) == sizeof(STRUCT_T), "Incompatible types passed");
    
        return *(reinterpret_cast<const STRUCT_T*>(&n));
    }
    
    // Приведение структур с битовыми полями к численному типу
    template <typename T, class STRUCT_T>
    T integral_cast(const STRUCT_T& s)
    {
        static_assert(std::is_integral<T>::value, "Integral type required as T");
        static_assert(std::is_class<STRUCT_T>::value, "class or struct type required as STRUCT_T");
        static_assert(sizeof(T) == sizeof(STRUCT_T), "Incompatible types passed");
    
        return *(reinterpret_cast<const T*>(&s));
    }

    Почему это UB?

    Запостил: YpaHeLI_, 12 Мая 2021

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

    • https://en.cppreference.com/w/cpp/language/reinterpret_cast
      Whenever an attempt is made to read or modify the stored value of an object of type DynamicType through a glvalue of type AliasedType, the behavior is undefined unless one of the following is true:

      AliasedType and DynamicType are similar.
      AliasedType is the (possibly cv-qualified) signed or unsigned variant of DynamicType.
      AliasedType is std::byte (since C++17), char, or unsigned char: this permits examination of the object representation of any object as an array of bytes.
      Ответить
      • > are similar.
        какой дефинишен)

        а если стрикт алайзинг отключить? или не поможет?
        Ответить
        • > какой дефинишен)
          В Стандарте есть формальное определение, просто оно (по традиции) длинное и запутанное.

          > а если стрикт алайзинг отключить?
          Поможет, просто отключатся някоторые оптимизации. Ну и код няпортабельный будет, конячно, хотя это по задаче смотреть нядо.
          Ответить
    • template <class To, class From>
      To struct_cast(const From & from)
      {
          static_assert(std::is_trivially_copyable_v<To>, "To must be trivially copyable");
          static_assert(std::is_trivially_copyable_v<From>, "From must be trivially copyable");
          static_assert(sizeof(From) == sizeof(To));
          
          To to;
          std::memcpy(std::addressof(to), std::addressof(from), sizeof(To));
          return to;
      }

      Примерня так будет по Стандарту.
      А с 20-й версии можня не городить велосипед: https://en.cppreference.com/w/cpp/numeric/bit_cast .
      Ответить

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