Переменная constexpr не захвачена

Следующий код не компилируется в clang (в GCC компилируется):

struct A{
    int a;
};

auto test(){
    constexpr A x{10};
    return []{
        return x; // <-- here x is A: clang doesn't compile
    }();
}

Ошибка Clang заключается в том, что переменная «x» не может быть неявно захвачена в лямбда-выражении без указания значения захвата по умолчанию, но я думал, что переменные constexpr всегда захватывались.

Если x является целым, код компилируется:

auto test(){
    constexpr int x{10};
    return []{
        return x; // <-- here x is int: clang is ok
    }();
}

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

auto test(){
    constexpr A x{10};
    return []{
        return x.a;
    }();
}

Кланг прав? Если да, то каково обоснование? Я использую -std=С++17

--РЕДАКТИРОВАТЬ--

Следующий вопрос: Могу ли я использовать значение constexpr в лямбде без его захвата? не имеет отношения к этому, так как с clang11 это больше не проблема: на самом деле, как указано выше, если x является целым числом, clang11 компилируется.

Пример кода также присутствует в https://godbolt.org/z/rxcYjz

Не забудьте добавить тег c++ к вопросам C++, чтобы больше пользователей увидели сообщение.

cigien 09.12.2020 23:48

«Следующий вопрос: Могу ли я использовать значение constexpr в лямбде без его захвата? Не связан с этим, так как с clang11 это больше не проблема: на самом деле, как указано выше, если x является int, clang11 компилируется ." Это буквально то же самое.

Asteroids With Wings 10.12.2020 13:01

@AsteroidsWithWings, разница в том, что в этом вопросе даже нельзя использовать int. Теперь int в порядке, любой другой объект - нет. Это все еще проблема с clang?

Mario Demontis 10.12.2020 13:26

@MarioDemontis Это не значит, что вы использовали int; это то, что вы назвали участника (что является odr-использованием x). Тот же вопрос и баг. x сам по себе не является int ни в одном из ваших примеров.

Asteroids With Wings 10.12.2020 14:35

Хорошо, теперь я добавил второй фрагмент между ними. Я не понимаю, почему 1-й не работает, а 2-й в порядке

Mario Demontis 10.12.2020 14:45

Не особенно полезно зацикливаться на всех возможных вариантах такой ошибки. Он сломан, это все, что вам нужно знать 🤣

Asteroids With Wings 10.12.2020 14:52

Может баг и похож, но не тот. Попробуйте скомпилировать фрагмент из «Могу ли я использовать значение constexpr в лямбда-выражении без его захвата?». Он также работает с clang5!

Mario Demontis 10.12.2020 15:02
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
8
7
156
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Когда вы return x; в первом примере, вы должны вызвать конструктор копирования A, который включает привязку ссылки к x и, таким образом, odr-использует его. Можно привести аргумент, что тривиальная копия значения, используемого в константных выражениях, не должна представлять собой использование odr больше, чем return x.a;, но в этом правиле нет такого исключения, поэтому Clang прав, отклонив его.

На практике вы, конечно, можете создать любую constexpr переменную static, чтобы избежать необходимости ее захвата.

В этом есть смысл. Спасибо

Mario Demontis 05.01.2021 13:20

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