Следующий код не компилируется в 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
«Следующий вопрос: Могу ли я использовать значение constexpr в лямбде без его захвата? Не связан с этим, так как с clang11 это больше не проблема: на самом деле, как указано выше, если x является int, clang11 компилируется ." Это буквально то же самое.
@AsteroidsWithWings, разница в том, что в этом вопросе даже нельзя использовать int. Теперь int в порядке, любой другой объект - нет. Это все еще проблема с clang?
@MarioDemontis Это не значит, что вы использовали int
; это то, что вы назвали участника (что является odr-использованием x
). Тот же вопрос и баг. x
сам по себе не является int
ни в одном из ваших примеров.
Хорошо, теперь я добавил второй фрагмент между ними. Я не понимаю, почему 1-й не работает, а 2-й в порядке
Не особенно полезно зацикливаться на всех возможных вариантах такой ошибки. Он сломан, это все, что вам нужно знать 🤣
Может баг и похож, но не тот. Попробуйте скомпилировать фрагмент из «Могу ли я использовать значение constexpr в лямбда-выражении без его захвата?». Он также работает с clang5!
Когда вы return x;
в первом примере, вы должны вызвать конструктор копирования A
, который включает привязку ссылки к x
и, таким образом, odr-использует его. Можно привести аргумент, что тривиальная копия значения, используемого в константных выражениях, не должна представлять собой использование odr больше, чем return x.a;
, но в этом правиле нет такого исключения, поэтому Clang прав, отклонив его.
На практике вы, конечно, можете создать любую constexpr
переменную static
, чтобы избежать необходимости ее захвата.
В этом есть смысл. Спасибо
Не забудьте добавить тег c++ к вопросам C++, чтобы больше пользователей увидели сообщение.