То, что вы делаете , может быть законным, но это зависит от реального определения class T
, поэтому мы не можем знать наверняка, основываясь на коде, который вы показали.
Начиная с C ++ 11 §3.9.2 / 3:
Разрешены указатели на неполные типы, хотя существуют ограничения на то, что с ними можно сделать.
Эти ограничения перечислены в §3.2 / 4:
Тип класса T
должен быть завершен, если:
- определен объект типа
T
или - объявлен элемент данных нестатического класса типа
T
, или T
используется в качестве типа объекта или типа элемента массива в new-выражение , или - преобразование lvalue-в-значение применяется к glvalue, ссылающемуся на объект типа
T
, или - - преобразование выражения (неявно или явно) для ввода
T
или - выражения, которое не является константой нулевого указателя и имеет тип, отличный от
void*
, преобразуется в type указатель на T
или ссылку на T
с использованием неявного преобразования, dynamic_cast
или static_cast
, или - оператор доступа к члену класса применяется к выражению типа
T
,или - оператор
typeid
или оператор sizeof
применяется к операнду типа T
, или - функция с типом возвращаемого значения или типом аргумента типа
T
определяется или вызывается, либо - определяется класс с базовым классом типа
T
, либо - присваивается lvalue типа
T
, либо - тип
T
является субъектом alignof
выражения или - объявление-исключение имеет тип
T
, ссылку на T
или указатель на T
.
Шестая пуля выглядит здесь уместно, как мы видим в §5.2.10 / 7, что reinterpret_cast
между типами указателей определяется в терминахиз static_cast
:
Указатель объекта может быть явно преобразован в указатель объекта другого типа.Когда значение v
типа «указатель на T1
» преобразуется в тип «указатель на cv T2
», результат равен static_cast<cv T2*>(static_cast<cv void*>(v))
, если T1
и T2
являются типами стандартной компоновки итребования по выравниванию T2
не являются более строгими, чем требования T1
, или если любой тип равен void
.Преобразование значения типа «указатель на T1
» в тип «указатель на T2
» (где T1
и T2
являются типами объектов и где требования по выравниванию T2
не являются более строгими, чем требования T1
) и возврат к исходному типу возвращает исходное значение указателя.Результат любого другого такого преобразования указателя не определен.
Но поскольку сначала reinterpret_cast
static_cast
с void*
, , а затем к реальному результирующему типу указателя, чтоШестая пуля не применяется.
Итак, пока вы все еще находитесь на законной территории, несмотря на то, что T
является неполным типом.Однако, если выясняется, что T
не является типом стандартного макета или имеет более строгие требования к выравниванию, чем int
, то последнее предложение в §5.2.10 / 7 остается верным, и вы вызываете UB.