Ist es möglich, den []
Bediener zweimal zu überlasten ? Um dies zu ermöglichen: function[3][3]
(wie in einem zweidimensionalen Array).
Wenn es möglich ist, würde ich gerne einen Beispielcode sehen.
c++
operator-overloading
Eispopo
quelle
quelle
operator()(int, int)
stattdessen zu überladen ...std::vector
mit einem Bereichskonstruktor: stackoverflow.com/a/25405865/610351using array2d = std::array<std::array<int, 3>, 3>;
Antworten:
Sie können überladen
operator[]
, um ein Objekt zurückzugeben, mit dem Sieoperator[]
erneut ein Ergebnis erhalten können.Dann können Sie es wie folgt verwenden:
Dies ist nur ein einfaches Beispiel. Sie möchten eine Reihe von Grenzprüfungen und anderen Dingen hinzufügen, aber Sie haben die Idee.
quelle
Proxy::operator[]
sollteint&
nicht nur zurückkehrenint
std::vector<std::vector<int>>
, um Memleak und seltsames Verhalten beim Kopieren zu vermeiden.multi_array
als auchextent_gen
sind gute Beispiele für diese Technik. boost.org/doc/libs/1_57_0/libs/multi_array/doc/…const ArrayOfArrays arr; arr[3][5] = 42;
werden in der Lage Zusammenstellung und Veränderungen passierenarr[3][5]
, die von dem, was der Benutzer Erwartung irgendwie anders ist , dasarr
istconst
.Proxy::operator[]
keinen Verweis in diesem Code zurück (vorausgesetzt, Ihr Kommentar ist keine Antwort auf Ryan Haining). Noch wichtiger ist, wennarr
is const ist,operator[]
kann es nicht verwendet werden. Sie müssten eine const-Version definieren und sie natürlich zurückgebenconst Proxy
. DannProxy
selbst hätte const und non-const Methoden. Und dann würde Ihr Beispiel immer noch nicht kompiliert, und der Programmierer würde sich freuen, dass im Universum alles in Ordnung und gut ist. =)Ein Ausdruck
x[y][z]
erfordert, dass erx[y]
zu einemd
unterstützten Objekt ausgewertet wirdd[z]
.Dies bedeutet , dass
x[y]
ein Objekt mit einem sein sollte ,operator[]
daß auswertet auf ein „Proxy - Objekt“ , das auch eine unterstütztoperator[]
.Nur so können sie verkettet werden.
Alternativ können Sie überladen
operator()
, um mehrere Argumente zu verwenden, die Sie möglicherweise aufrufenmyObject(x,y)
.quelle
Insbesondere bei einem zweidimensionalen Array kann es vorkommen, dass Sie eine einzelne Operator [] -Überladung haben, die einen Zeiger auf das erste Element jeder Zeile zurückgibt.
Anschließend können Sie mit dem integrierten Indizierungsoperator auf jedes Element in der Zeile zugreifen.
quelle
Es ist möglich, wenn Sie beim ersten [] Aufruf eine Art Proxy-Klasse zurückgeben. Es gibt jedoch eine andere Option: Sie können operator () überladen, das eine beliebige Anzahl von Argumenten (
function(3,3)
) akzeptieren kann .quelle
Ein Ansatz ist
std::pair<int,int>
:Natürlich darfst du
typedef
daspair<int,int>
quelle
nValue = theArray[{2,3}];
Sie können ein Proxy-Objekt verwenden, etwa so:
quelle
Es würde groß sein , wenn Sie mich , was sie wissen
function
,function[x]
undfunction[x][y]
sind. Aber lassen Sie mich es trotzdem als ein Objekt betrachten, das irgendwo wie deklariert wurde(Da Sie sagten, dass es sich um eine Überlastung des Operators handelt, werden Sie sich wahrscheinlich nicht für Array-ähnliche interessieren.
SomeClass function[16][32];
)So
function
ist eine Instanz des TypsSomeClass
. Suchen Sie dann nach der DeklarationSomeClass
für den Rückgabetyp deroperator[]
Überladung, genau wieReturnType operator[](ParamType);
Dann
function[x]
wird der Typ habenReturnType
. Suchen Sie erneut nachReturnType
deroperator[]
Überlastung. Wenn es eine solche Methode gibt, können Sie den Ausdruck verwendenfunction[x][y]
.Beachten Sie , im Gegensatz zu
function(x, y)
,function[x][y]
sind 2 separate Anrufe. Daher ist es für Compiler oder Laufzeit schwierig, die Atomizität zu gewährleisten, es sei denn, Sie verwenden eine Sperre im Kontext. Ein ähnliches Beispiel ist, libc sagt,printf
ist atomar, während sukzessive Aufrufe an den überlastetenoperator<<
Ausgabestream nicht sind. Eine Aussage wieMöglicherweise gibt es ein Problem mit Multithread-Anwendungen, aber so etwas wie
ist gut.
quelle
quelle
Ich habe meine eigene einfache Lösung dafür gefunden.
quelle
Auf diese Weise können Sie ein Lambda nehmen und einen Indexer (mit
[]
Unterstützung) erstellen .Angenommen, Sie haben eine
operator()
, die die Übergabe beider Koordinaten an onxe als zwei Argumente unterstützt. Jetzt ist das Schreiben von[][]
Unterstützung nur noch:Und fertig. Keine benutzerdefinierte Klasse erforderlich.
quelle
Wenn Sie anstelle von [x] [y] ein [{x, y}] sagen möchten, können Sie Folgendes tun:
quelle
Es ist möglich, mehrere [] mit einem speziellen Vorlagenhandler zu überladen. Nur um zu zeigen, wie es funktioniert:
Und jetzt die Definition
SubscriptHandler<ClassType,ArgType,RetType,N>
, damit der vorherige Code funktioniert. Es zeigt nur, wie es gemacht werden kann. Diese Lösung ist weder optimal noch fehlerfrei (zum Beispiel nicht threadsicher).quelle
Mit einer
std::vector<std::vector<type*>>
können Sie den inneren Vektor mithilfe eines benutzerdefinierten Eingabeoperators erstellen, der Ihre Daten durchläuft und einen Zeiger auf die einzelnen Daten zurückgibt.Beispielsweise:
Live Beispiel
Diese Lösung bietet den Vorteil, dass Sie einen echten STL-Container erhalten, sodass Sie spezielle Funktionen für Schleifen, STL-Algorithmen usw. verwenden können.
Es werden jedoch Vektoren von Zeigern erstellt. Wenn Sie also kleine Datenstrukturen wie diese verwenden, können Sie den Inhalt direkt in das Array kopieren.
quelle
Beispielcode:
quelle
Vektor <Vektor <T>> oder T ** ist nur erforderlich, wenn Sie Zeilen mit variabler Länge und viel zu ineffizienter Speichernutzung / Zuweisung haben, wenn Sie ein rechteckiges Array benötigen. siehe at () Methode:
quelle
Mit C ++ 11 und der Standardbibliothek können Sie ein sehr schönes zweidimensionales Array in einer einzigen Codezeile erstellen:
Indem Sie entscheiden, dass die innere Matrix Zeilen darstellt, greifen Sie mit einer
myMatrix[y][x]
Syntax auf die Matrix zu :Und Sie können Fernkampf
for
für die Ausgabe verwenden:(Die Entscheidung, ob die inneren
array
Spalten Spalten darstellen, würde einefoo[x][y]
Syntax ermöglichen, aber Sie müssten umständlicherefor(;;)
Schleifen verwenden, um die Ausgabe anzuzeigen.)quelle
Meine 5 Cent.
Ich wusste intuitiv, dass ich viel Boilerplate-Code machen muss.
Aus diesem Grund habe ich anstelle von operator [] den Operator (int, int) überladen. Dann habe ich im Endergebnis anstelle von m [1] [2] m (1,2)
Ich weiß, dass es eine andere Sache ist, aber es ist immer noch sehr intuitiv und sieht aus wie eine mathematische Schrift.
quelle
Die kürzeste und einfachste Lösung:
quelle