Vor nicht allzu langer Zeit waren Anforderungsausdrücke (der durch den zweiten eingeführte Ausdruck erfordert) in Einschränkungsausdrücken (der durch den ersten eingeführte Ausdruck erfordert) nicht zulässig. Es konnte nur in Konzeptdefinitionen erscheinen. Genau dies wird in dem Abschnitt dieses Papiers vorgeschlagen, in dem diese Behauptung erscheint.
Im Jahr 2016 gab es jedoch einen Vorschlag, diese Einschränkung zu lockern [Anmerkung des Herausgebers: P0266 ]. Beachten Sie den durchgestrichenen Absatz 4 in Abschnitt 4 des Papiers. Und so wurde geboren erfordert erfordert.
Um die Wahrheit zu sagen, ich hatte diese Einschränkung nie in GCC implementiert, also war es immer möglich gewesen. Ich denke, dass Walter das entdeckt und nützlich gefunden hat, was zu diesem Papier geführt hat.
Damit niemand glaubt, dass ich nicht empfindlich auf das Schreiben reagiere, habe ich einige Zeit damit verbracht, herauszufinden, ob dies vereinfacht werden kann. Kurze Antwort: nein.
Das Problem ist, dass nach einer Vorlagenparameterliste zwei grammatikalische Konstrukte eingeführt werden müssen: sehr häufig ein Einschränkungsausdruck (wie P && Q
) und gelegentlich syntaktische Anforderungen (wie requires (T a) { ... }
). Das nennt man einen Anforderungsausdruck.
Das erste erfordert die Einführung der Einschränkung. Die zweite Anforderung führt den erforderlichen Ausdruck ein. So komponiert die Grammatik. Ich finde es überhaupt nicht verwirrend.
Ich habe einmal versucht, diese auf eine einzige Anforderung zu reduzieren. Leider führt dies zu einigen ernsthaft schwierigen Analyseproblemen. Sie können beispielsweise nicht leicht erkennen, ob a (
after the require einen verschachtelten Unterausdruck oder eine Parameterliste bezeichnet. Ich glaube nicht, dass es eine perfekte Disambiguierung dieser Syntax gibt (siehe die Begründung für eine einheitliche Initialisierungssyntax; dieses Problem gibt es auch).
Sie treffen also eine Wahl: make erfordert die Einführung eines Ausdrucks (wie jetzt) oder die Einführung einer parametrisierten Liste von Anforderungen.
Ich habe mich für den aktuellen Ansatz entschieden, weil ich die meiste Zeit (wie in fast 100% der Fälle) etwas anderes als einen erforderlichen Ausdruck möchte. Und in dem äußerst seltenen Fall, dass ich einen Anforderungsausdruck für Ad-hoc-Einschränkungen wollte, macht es mir wirklich nichts aus, das Wort zweimal zu schreiben. Es ist ein offensichtlicher Indikator dafür, dass ich keine ausreichend solide Abstraktion für die Vorlage entwickelt habe. (Denn wenn ich es hätte, hätte es einen Namen.)
Ich hätte mich dafür entscheiden können, dass die Anforderungen einen Anforderungen-Ausdruck einführen. Das ist tatsächlich schlimmer, weil praktisch alle Ihre Einschränkungen so aussehen würden:
template<typename T>
requires { requires Eq<T>; }
void f(T a, T b);
Hier wird die zweite Anforderung als verschachtelte Anforderung bezeichnet. es wertet seinen Ausdruck aus (anderer Code im Block des erforderlichen Ausdrucks wird nicht ausgewertet). Ich denke, das ist viel schlimmer als der Status Quo. Jetzt müssen Sie zweimal überall schreiben.
Ich hätte auch mehr Schlüsselwörter verwenden können. Dies ist ein eigenständiges Problem - und es ist nicht nur ein Fahrradschuppen. Es könnte eine Möglichkeit geben, Schlüsselwörter "neu zu verteilen", um die Duplizierung zu vermeiden, aber ich habe nicht ernsthaft darüber nachgedacht. Aber das ändert nichts an der Essenz des Problems.
noexcept(noexcept(...))
.