Понимание примера преобразования lvalue в rvalue

Мне трудно понять, как этот код (пример из проекта стандарта C++14 [conv.lval]) вызывает неопределенное поведение для g(false), Почему constexpr сделать программу действительной?

Кроме того, что означает "не доступ y.n"? В обоих звонках g() мы возвращаем n элемент данных, так почему последняя строка говорит, что не имеет к нему доступа?

struct S { int n; };
auto f() {
    S x { 1 };
    constexpr S y { 2 };
    return [&](bool b) { return (b ? y : x).n; };
}
auto g = f();
int m = g(false); // undefined behavior due to access of x.n outside its
                  // lifetime
int n = g(true);  // OK, does not access y.n

1 ответ

Решение

Это потому что y.n не используется odr и поэтому не требует доступа к y.n правила использования odr описаны в 3.2 и говорит:

Переменная x, имя которой появляется в качестве потенциально оцениваемого выражения ex, используется odr, если только при применении преобразования lvalue-to-rvalue (4.1) в x не получается константное выражение (5.19), которое не вызывает никаких нетривиальных функций и, если x является объектом, ex является элементом набора потенциальных результатов выражения e, где к e применяется либо преобразование lvalue-в-значение (4.1), либо e является выражением отброшенного значения

Обратите внимание, что Бен Фойгт сделал несколько полезных комментариев, которые немного прояснили этот вопрос. Таким образом, рабочее предположение здесь, что х будет:

y

и e будет (другое выражение, для которого определено e, рассматривается в пункте 2 раздела 3.2):

(b ? y : x).n

y дает константное выражение и преобразование lvalue в rvalue применяется к выражению e.

поскольку f дает лямбду, которая захватывает f локальные переменные по ссылке x больше не действителен после звонка f сделано с x это автоматическая переменная внутри f, поскольку y является постоянным выражением, оно действует так, как будто y.n не был доступен, и поэтому у нас нет той же проблемы жизни.

Ваш пример включен в раздел N3939 4.1 [conv.lval] и прямо перед этим примером написано:

Когда преобразование lvalue в rvalue применяется к выражению e, и либо

и включает в себя следующую маркировку, к которой относится исследование:

оценка e приводит к оценке члена ex из набора потенциальных результатов e, и ex называет переменную x, которая не используется odr в ex (3.2),

затем:

значение, содержащееся в ссылочном объекте, не доступно

Это было применено к проекту стандарта C++14 из-за сообщения об ошибке 1773.

Другие вопросы по тегам