Wie kann man eine variablenbasierte verkettete Indexierungsfunktion erstellen?
Wenn ich ein Objekt habea
dass entweder ein eingebautes Array oder ein Klassentyp mit einem geeignetenoperator []
, und sein zurückgegebener Typ kann selbst indiziert werden. Wie soll ich eine generische Funktion schreiben, die alle mit einem variadischen Aufruf anstelle eines getrennten Klammerblocks indizieren kann? Mit anderen Worten, ich kann Ausdrücke machen wie:
<code>a[i0][i1]...[iK] </code>
und ich möchte es als einzelne Funktion schreiben können:
<code>slice( a, i0, i1, ..., iK ) </code>
da die Regeln von C ++ erfordernoperator []
um an einzelnen Argumenten zu arbeiten, was die Kompatibilität mit verschiedenen Sachen beeinträchtigt. (Diese Frage basiert auf einem Usenet-Thread, in dem ich versucht habe, etwas Ähnliches zu fragen. Am Ende habe ich selbst nur möglicherweise verschachtelte eingebaute Arrays gelöst.)
Ein erster Stich:
<code>template < typename T, typename U > constexpr auto slice( T &&t, U &&u ) noexcept(???) -> ??? { return ce_forward<T>(t)[ ce_forward<U>(u) ]; } template < typename T, typename U, typename V, typename ...W > constexpr auto slice( T &&t, U &&u, V &&v, W... &&w ) noexcept(???) -> ??? { return slice( ce_forward<T>(t)[ce_forward<U>(u)], ce_forward<V>(v), ce_forward<W>(w)... ); } </code>
Dasce_forward
Funktionsvorlagen sind aconstexpr
-markiertstd::forward
. (Einige Dinge in der Norm, die markiert werden könntenconstexpr
Ich versuche, das richtige Material für die Rückgabetyp- und Ausnahmespezifikationspunkte zu finden. Einige mir bekannte Fälle und Vorbehalte sind:
operator []
erfordert, dass ein Operand ein Datenzeiger (oder eine verfallene Arrayreferenz) und der andere ein Aufzählungs- oder Ganzzahltyp ist. Die Operanden können in beliebiger Reihenfolge sein. Ich weiß nicht, ob ein Operand durch einen Klassentyp mit einer eindeutigen (nicht expliziten?) Konvertierung in einen geeigneten Typ ersetzt werden könnte.Ein Klassentyp kann definierenoperator []
als nicht statische Mitgliedsfunktion (en). Jede solche Funktion kann nur einen Parameter haben (außerthis
).Der eingebaute Operator kann nicht werfen. (Sofern Operanden nicht auf einer UDT-Konvertierung basieren könnten, ist diese Konvertierung der einzig mögliche Auslösepunkt.) Das undefinierte Verhalten, das durch Grenzfehler verursacht wird, liegt hier außerhalb unseres Zuständigkeitsbereichs.Ob der letzte Indexaufruf eine l-Wert-Referenz, eine r-Wert-Referenz oder einen Wert zurückgibt, sollte sich im Rückgabetyp von widerspiegelnslice
.Wenn der (letzte?) Aufruf By-Value ist, dannstd::is_nothrow_move_constructible<ReturnType>::value
sollte nach der Ausnahmespezifikation ODER-verknüpft sein. (Nachschlagewerke sindnoexcept
.)Wenn der eingebaute Operator ein Array enthält, sollte die zurückgegebene Referenz für diesen Schritt eine r-Wert-Referenz sein, wenn das Array auch eine ist. (Dies ist ein gewisser Fehler, da Zeiger im Gegensatz zu Arrays den L- / R-Wert-Status ihres Ziels verlieren, sodass die traditionelle Rückgabe immer eine L-Wert-Referenz ist.)Stellen Sie für Indizierungsoperatoren vom Typ class sicher, dass die Abschnitte exception-spec und return-type auf dieselbe Überladung verweisen (wenn mehr als eine vorhanden ist), die der Funktionskörper verwendet. Seien Sie vorsichtig bei Überlastungen, die sich nur in der Qualifikation von unterscheidenthis
(const
/volatile
/ beide / keine und / oder&
/&&
/weder).