Czy dozwolone wyrażenia mogą „wychwytywać” zmienne obejmującego zakres?

10

W poniższym przykładzie argumenty funkcji są używane do testowania wymaganym wyrażeniem, czy wyrażenie, które ich używa, jest poprawnie utworzone. Wymagane wyrażenie nie przyjmuje żadnych argumentów; wykorzystuje bezpośrednio zmienne w zakresie funkcji:

#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);
}

Powyższy kod kompiluje się z gałęzią pojęć Clanga. Jednak GCC10 przyjmuje tylko połączenie z Resize. GCC9 ICE. Czy Clang ma rację, akceptując to?

metalfox
źródło
2
ICE jest zawsze problemem kompilatora.
Jarod42
Powiedziałbym, że albo należy go odrzucić, jeśli kod nie jest dozwolone, aby uchwycić zmiennej lokalnej (tak jak Resizei Eziserpowinien odrzucić) lub zarówno funkcja powinna skompilować. Powiedziałbym, że clang ma rację.
Jarod42
@ Jarod42 Tak. Zachowanie GCC jest wyraźnie błędne. Złożę PR. Myślę też, że Clang ma rację, ale chciałbym to potwierdzić.
metalfox,

Odpowiedzi:

6

Tak, wyrażenie wymagające może wykorzystywać wszystko, co jest w zasięgu. Trzeba tylko typ czegokolwiek niej nazwisk, mimo wszystko, z wyjątkiem w zagnieżdżonych-wymogu lub innej stałej ekspresji. Dotyczy to zarówno deklaracji otaczających, jak i własnych (formalnych) parametrów.

[expr.prim.req] / 5 :

Treść wymagań zawiera sekwencję wymagań . Wymagania te mogą odnosić się do parametrów lokalnych, parametrów szablonu i wszelkich innych deklaracji widocznych z otaczającego kontekstu.

Davis Herring
źródło