Этот вопрос относится к текущей версии C ++ 20. Цитируемые отрывки были немного изменены по сравнению с предыдущими стандартными итерациями, но насколько я знаю, не соответствующими способами.
Я ищу разъяснения по поводу терминов " нарушение псевдонимов"или" строгое нарушение псевдонимов".
Мое предыдущее впечатление заключалось в том, что эти термины конкретно относятся к нарушениям стандартного пункта [basi c .lval] / 11 :
Если программа пытается получить доступ ([defns.access]) к сохраненному значению объекта через glvalue, тип которого не похож ([conv.qual]) на один из следующих типы поведение не определено:
- тип объекта Dynami c,
- тип, который является типом со знаком или без знака, соответствующим типу Dynami c объекта объект или
- a
char
, unsigned char
или std::byte
type.
Если программа вызывает дефолтный конструктор копирования / перемещения или оператор назначения копирования / перемещения для объединение типа U с аргументом glvalue th at не обозначает объект типа cv U в течение его времени жизни, поведение не определено. [Примечание: в отличие от C, C ++ не имеет доступа к типу класса. - конечная заметка]
Примечание в конце уточняется посредством примечаний и нормативных ссылок в [defns.access] , означающих, что к можно получить доступ только к скалярным типам . См. Также раздел примечаний на соответствующей странице cppreference .
Поэтому мне кажется, что этот абзац никогда не может применяться к доступу к не принадлежащим к классу c членам классов через неправильный класс введите и что « (строгое) нарушение псевдонимов » не может применяться, например, к следующему примеру:
struct A { void f() {}; int a; };
struct B { void f() {}; int a; };
int main() {
auto a = new A; // aligned for all non-overaligned types
B& b = reinterpret_cast<B&>(*a);
b.f(); //1
b.a = 1; //2
}
Предположим, что sizeof(A) == sizeof(B)
и offsetof(A, a) == offsetof(B, b)
(хотя я тоже не думаю, имеет значение, и последнее тривиально, потому что классы имеют стандартную компоновку). Другой вариант интереса будет struct A { };
, но, опять же, я думаю, что разницы не будет.
В случае b.f()
нет доступа к любому скалярному объекту вообще. Согласно [expr.ref] , в последнем случае объект, на который ссылаются, должен быть элементом данных a
объекта B
, на который ссылается b
, но поскольку это явно не существует, я полагаю, формирование доступа к члену уже может быть неопределенным поведением?
И //1
, и //2
должны явно быть неопределенным поведением в некотором смысле. Я думаю, что //1
нарушает [class.mfct.non-static] / 2 , но я не совсем уверен, какой пункт //2
точно нарушает.
Какие стандартные абзацы делают два строки //1
и //2
точно нарушают, и считается ли это нарушение включенным в термины " (строгое) нарушение псевдонимов "?