Bei Verwendung einer Typeinschränkung für ein Weiterleitungsreferenzargument wird die Einschränkung als L-Wert-Referenz auf den Typ angegeben. Beispielsweise wird der Aufruf von h im folgenden Code nicht kompiliert, da std::integral zum Halten erforderlich wäre, Integral jedoch für Referenzen nicht wahr ist (siehe
https://godbolt.org/z/Taeb5Exdv):
Code: Select all
#include
void f(std::integral auto &i) {}
void g(const std::integral auto &i) {}
void h(std::integral auto &&i) {}
int main() {
int one = 1;
f(one);
g(one);
h(one); // "[...] the expression 'is_integral_v [with _Tp = int&]' evaluated to 'false'"
}
(Der Fehler ist für mich kontraintuitiv, da f und g eher Integral als Integral auswerten.
, also hat mein Verstand das unbewusst auf eine „Regel“ wie „Cvref wurde aus den Vorlagenargumenten entfernt“ extrapoliert. Aber okay, es ist komplizierter; Weiterleitungsreferenzen sind unterschiedlich, wahrscheinlich aus einem bestimmten Grund; Ich kann akzeptieren, dass dies einfach „die Art und Weise ist, wie es funktioniert“.)
Ich kann dies umgehen, indem ich h durch z. B. ersetze. (siehe
https://godbolt.org/z/fa9f7eeq6)
Code: Select all
void h1(auto &&i) requires std::integral {}
oder
Code: Select all
template
void h2(T &&i) requires std::integral {}
oder
Code: Select all
template
concept Integral_without_cvref = std::integral;
void h3(Integral_without_cvref auto &&i) {}
Alle sind etwas kompliziert: h1 und h2 erfordern mehr Syntax in den Funktionsdeklarationen und h3 erfordert ein spezielles Konzept.
Gibt es eine idiomatischere/prägnantere Möglichkeit, Einschränkungen für die Weiterleitung von Referenzargumenten zu deklarieren?