Sind erforderliche Ausdrücke zulässig, um Variablen des umschließenden Bereichs zu erfassen?

10

Im folgenden Beispiel werden die Funktionsargumente verwendet, um mit einem erforderlichen Ausdruck zu testen, ob ein Ausdruck, der sie verwendet, gut geformt ist. Der Requires-Ausdruck benötigt keine Argumente. Es verwendet die Variablen im Funktionsumfang direkt:

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

Der obige Code wird mit dem Zweig Clang-Konzepte kompiliert. GCC10 nimmt jedoch nur den Anruf an an Resize. GCC9 ICEs. Hat Clang Recht, es zu akzeptieren?

Metallfuchs
quelle
2
ICE ist immer ein Compiler-Problem.
Jarod42
Ich würde sagen, dass es entweder Code ablehnen sollte, wenn es nicht erlaubt ist, lokale Variablen zu erfassen (also beide Resizeund Ezisersollten abgelehnt werden) oder beide Funktionen kompiliert werden sollten. Ich würde sagen, Klirren ist richtig.
Jarod42
@ Jarod42 Ja. Das GCC-Verhalten ist eindeutig fehlerhaft. Ich werde eine PR einreichen. Ich denke auch, dass Clang Recht hat, aber ich möchte es bestätigen.
Metalfox

Antworten:

6

Ja, ein Requires-Ausdruck kann alles verwenden, was im Geltungsbereich liegt. Es braucht schließlich nur den Typ von irgendetwas, das es benennt, außer in einer verschachtelten Anforderung oder einem anderen konstanten Ausdruck. Dies gilt für umgebende Deklarationen ebenso wie für ihre eigenen (formalen) Parameter.

[expr.prim.req] / 5 :

Der Anforderungskörper enthält eine Folge von Anforderungen . Diese Anforderungen können sich auf lokale Parameter, Vorlagenparameter und andere Deklarationen beziehen, die im umschließenden Kontext sichtbar sind.

Davis Herring
quelle