Разрешено ли выражениям «требуется» захватывать переменные вмещающей области?

10

В следующем примере аргументы функции используются для проверки с помощью выражения require, правильно ли сформировано выражение, использующее их. Выражение require не имеет аргументов; он напрямую использует переменные в области действия функции:

#include <cstddef>
#include <vector>

template<typename T>
void Resize(T &v, std::size_t const n)
{
  if constexpr (requires { v.resize(n); })
    v.resize(n);
}

template<typename T>
void Eziser(T &v, std::size_t const n)
{
  if constexpr (requires { v.eziser(n); })
    v.eziser(n);
}

int main()
{
  std::vector<int> v;

  Resize(v, 10u);
  Eziser(v, 10u);
}

Приведенный выше код компилируется с веткой концепций Clang. Однако GCC10 принимает только вызов Resize. GCC9 ICE. Прав ли Кланг принять это?

metalfox
источник
2
ICE - это всегда проблема компилятора.
Jarod42
Я бы сказал, что либо он должен отклонять код, если ему не разрешено захватывать локальную переменную (поэтому оба Resizeи Eziserдолжны быть отклонены), либо обе функции должны компилироваться. Я бы сказал, что лязг прав.
Jarod42
@ Jarod42 Да. Поведение GCC явно глючит. Я подам PR. Я также думаю, что Clang прав, но я хотел бы подтвердить.
metalfox

Ответы:

6

Да, выражение require может использовать все, что находится в области видимости. В конце концов, ему нужен только тот тип, который он называет, кроме как во вложенном требовании или другом константном выражении. Это верно как для окружающих объявлений, так и для собственных (формальных) параметров.

[expr.prim.req] / 5 :

Требование тело содержит последовательность требований . Эти требования могут относиться к локальным параметрам, параметрам шаблона и любым другим объявлениям, видимым из окружающего контекста.

Дэвис Херринг
источник