Невозможно однозначно ответить по единственной строке `static Ref<T> FromThis(T* data)` — нужно видеть, что именно вы делаете с `data` внутри функции и какие типы фактически читаются/пишутся. Пока — кратко о главном, чтобы вы могли сами проверить свой код.
Коротко о правиле strict aliasing
- В C++ чтение/запись объекта через lvalue выражение допустимо только если тип lvalue:
- точно совпадает с динамическим/статическим типом объекта, или
- является совместимым (layout‑compatible) типом (редко в C++), или
- — для объектов класса — является базовым классом этого объекта (доступ к соответствующему субобъекту), или
- это char/unsigned char/std::byte (доступ к байтам объекта), или
- это синоним типа (typedef) или одинаковый cv‑вариант, и ещё ряд частных случаев (например, для совместимых стандартных layout типов).
- Доступ через несовместимый тип — UB: компилятор может оптимизировать исходя из предположения, что такие алиасы не происходят.
Когда нарушение происходит (типичные ненадёжные паттерны)
- Вы делаете reinterpret_cast<T2*>(ptr) и затем разыменовываете его, а реальный объект — другого, несовместимого типа T1.
- Вы храните/извлекаете объекты через общую память, не соблюдая правила для тривиальных типов (например, пишете один тип, потом читаете другой).
- Вы используете указатели на разные несвязанные классы как будто они указывают на одно и то же место и читаете через несовместимый тип.
Когда всё в порядке
- Функция просто принимает T* и создаёт Ref<T> (т.е. хранит/использует тот же T*): это нормально.
- Вы приводите T* к указателю на базовый класс при реальном объекте производного класса — доступ к базовому субобъекту допустим.
- Вы обращаетесь к объекту через char*/unsigned char*/std::byte* для байтового доступа — это явно разрешено.
- Для тривиальных типов можно безопасно копировать битово (memcpy), и это не нарушает правило.
Пример опасного кода
- Неправильно:
- U* up = reinterpret_cast<U*>(data); *up = ...; // если объект по data — не U и типы несовместимы — UB.
- Правильно:
- Если нужен побайтовый доступ — использовать reinterpret_cast<char*>(data) и читать/писать байты.
- Если нужно преобразовать битовое представление тривиального типа в другой тривиальный — использовать std::memcpy или std::bit_cast (C++20).
Рекомендации
- Покажите полный код тела FromThis и то, какие типы в нём используются — тогда дам конкретный ответ.
- Если вы делаете пининги/типпаны: рассмотрите std::bit_cast / memcpy / char* / union (с осторожностью) или отключение -fstrict-aliasing в крайнем случае.
- Для C++17/C++20 обратите внимание на std::launder, если имеете дело с размещённым new и повторным использованием storage.
Если пришлёте полный фрагмент (тело функции, что такое Ref<T>, какие касты делаются), я проверю конкретно и скажу, где именно есть UB и как исправить.