оператор запятой делает лямбда-выражение не constexpr - PullRequest
0 голосов
/ 22 ноября 2018

Согласно [это Q & A] , поскольку оператор запятой c ++ 11 поддерживает constexpr.Согласно [этим вопросам и ответам] переменная constexpr не должна быть захвачена лямбда-выражением, а должна использоваться внутри ее тела.

Оба эти правила делают следующий код, компилируемый в clang:

//Example 1

template <int>
struct Foo {};

int main() {
    constexpr int c = 1;
    static_cast<void>(Foo<(c, 2)>{});
}

//Example 2

template <int>
struct Foo {};

int main() {
    constexpr int c = 1;
    auto lambda = []{return c * 2;};
    static_cast<void>(Foo<lambda()>{});
}

Однако, хотя оба этих примера успешно компилируются в clang (который объявляет поддержку lambda constexpr, то есть - 8.0.0), следующий фрагмент не работает, и я не могу представить, почему ... Любые идеи?

template <int>
struct Foo {};

int main() {
    constexpr int c = 1;
    auto lambda = []{return (c, 2);};
    static_cast<void>(Foo<lambda()>{});
}

Ошибка компиляции:

переменная 'c' не может быть неявно захвачена в лямбда-выражении без указания захвата по умолчанию

[live демо]

Ответы [ 2 ]

0 голосов
/ 23 ноября 2018

Это ошибка clang, если мы посмотрим на более простой случай:

constexpr int c = 1;
auto lambda =  [] {return c,2;};

clang также считает это плохо сформированным ( смотри вживую ), лямбда требуется длязахватить автоматическую переменную, если она использует odr, см. expr.prim.lambda.capturep8 :

Объект захватывается, если он захвачен явно или неявно.Сущность, захваченная лямбда-выражением, используется в области видимости, содержащей лямбда-выражение.Если * это захвачено локальным лямбда-выражением, его ближайшая включающая функция должна быть нестатической функцией-членом.Если лямбда-выражение или создание шаблона оператора вызова функции универсальной лямбды odr-использует this или переменную с автоматической продолжительностью хранения из своей достигающей области, то эта сущность должна быть захвачена лямбда-выражением ,Если лямбда-выражение захватывает сущность, и эта сущность не определена или не захвачена в непосредственно включающем лямбда-выражении или функции, программа является некорректной....

и выражение отброшенного значения не используется odr .

Я нашел похожее сообщение об ошибке [отклонено допустимо] constexpr non-скалярная переменная не может использоваться в лямбда-выражениях без захвата или локального класса .

0 голосов
/ 22 ноября 2018

Кажется, это ошибка лягушки, согласно [basic.def.odr] / 4 :

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

Как уже отмечалось, проблема не ограничивается оператором запятой, но для каждого отброшенного выражения это выражение не составляет odr-use , следовательно, оно должно быть принято.

...