На термин "(строгое) нарушение псевдонимов", относящийся к доступу членов - PullRequest
7 голосов
/ 27 февраля 2020

Этот вопрос относится к текущей версии 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 точно нарушают, и считается ли это нарушение включенным в термины " (строгое) нарушение псевдонимов "?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...