Как использовать значение constexpr в лямбда?

Я хотел бы использовать значение constexpr в lambda. Чтение ответа на Используя lambda capture constexpr значение как размер массива, я предположил, что следующее должно работать:

  #include<array>
  int main()
  { 
    constexpr int i = 0;
    auto f = []{  
      std::array<int, i> a;
    };
    return 0;
  }

Однако, Clang 3.8 (с std = С++ 14) жалуется, что

переменная 'i' не может быть неявно зафиксирована в лямбда без установленный по умолчанию

Если это считать ошибкой в ​​clang 3.8?

BTW:

Вышеприведенный код компилируется с помощью gcc 4.9.2. Если я изменил выражение лямбды, чтобы зафиксировать явно:

...
auto f = [i]{
...

clang 3.8 компилирует его, но gcc 4.9.2 сбой:

ошибка: значение 'i не может использоваться в постоянном выражении...

Ответы

Ответ 1

Если это считать ошибкой в ​​clang 3.8?

Угу. Захват нужен только в том случае, если [expr.prim.lambda]/12 требует:

введите описание изображения здесь

Обратите внимание, в частности, на выделенный пример. f(x) не требует захвата x, потому что он не используется odr (разрешение перегрузки выбирает перегрузку с параметром объекта). Такая же аргументация применяется к вашему коду - [basic.def.odr]/3:

Переменная x, имя которой отображается как потенциально оцененное выражение ex является odr-используемым ex , если не применить преобразование lvalue-to-rvalue (4.1) до x дает постоянное выражение (5.20), которое не вызывает любые нетривиальные функции...

Это требование, безусловно, выполнено.

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

i - это его набор потенциальных результатов в соответствии с [basic.def.odr]/(2.1), и преобразование ltr действительно применяется сразу же, поскольку оно передается нестандартному шаблону параметра типа объекта.

Следовательно, как мы показали, (12.1) неприменимо - и (12.2), очевидно, тоже не является - Clang ошибочно отвергает ваш фрагмент.