Ich versuche eine Quadtree-Sparse-Matrix-Klasse zu schreiben. Kurz gesagt, ein quadtree_matrix<T>
ist entweder die Nullmatrix oder ein vierfaches (ne, nw, se, sw)
von quadtree_matrix<T>
.
Ich möchte schließlich verschiedene Zuordnungsschemata testen, da dies wahrscheinlich die Leistung von Operationen der linearen Algebra beeinflussen wird. Also werde ich auch die Vorlage quadtree_matrix
auf einem Standard-Zuordnungstyp verwenden, damit ich vorhandene Zuordner wiederverwenden kann.
Ich muss zwei verschiedene Arten von Daten zuweisen: entweder ein T
oder ein node
, das vier Zeiger enthält (entweder zu T oder zu Knoten). Für all die Algorithmen, die ich in Betracht ziehe, weiß ich mit Sicherheit, welche Art von Daten zu erwarten sind, weil ich weiß, welche Größen der Submatrizen an irgendeinem Punkt des Algorithmus vorliegen (ich muss diese Größen nicht einmal speichern).
Ich werde natürlich zwei verschiedene Allokatoren verwenden: Das ist in Ordnung, da Allokator-Typen die Vorlage rebind
und einen Vorlagenkopie-Konstruktor bereitstellen (und als Werttypen verwendet werden sollen, wie die get_allocator
Mitglieder des Standards) Behälter schlagen vor, indem sie eine Kopie zurückbringen).
Das Problem besteht darin, dass Zuordnungselementfunktionen einen bestimmten pointer
-Typ verwenden, der kein Vanilla-Zeiger sein muss. Einige Zuweiser (Boost-Interprocessor-Zuweiser) verwenden diese Funktion ausgiebig.
Wenn die Zuweisungs-Zeigertypen Garten-Varietät-Zeiger wären, hätte ich keine Probleme: Zumindest könnte ich Zeiger verwenden, um sie aufzulösen und neu zu interpretieren (entweder node*
oder T*
). Ich könnte auch eine Verbindung verwenden (wahrscheinlich besser).
Soweit ich weiß, gibt es keine Anforderung für die PODness der allocator::pointer
-Typen. Sie müssen nur Zufallszugriffs-Iteratoren sein.
Nun, meine Frage ist:
Gibt es für eine Zuweisungsklassenvorlage A<T>
(oder deren äquivalente A::rebind<T>::other
) eine Garantie für:
A<T>::pointer
auf A<U>::pointer
zu übertragen, vorausgesetzt U
ist eine zugängliche Basis von T
? A<T>::pointer
auf A<U>::pointer
zu provisionieren, vorausgesetzt T
ist eine zugängliche Basis von U
und der "Laufzeittyp" (was auch immer in diesem Zusammenhang gemeint ist) des Castees ist U
? A<void>::pointer
(wenn das sinnvoll ist)? Oder gibt es eine Lösung für mein Problem, über das ich nicht nachgedacht habe?
Aus den Tabellen in 20.1.5 / 2 wird deutlich, dass der Typ von A<T>::pointer
"Zeiger auf T
" sein muss. Da diese Zeigertypen normalerweise konvertierbar sind, sind Ihre 1 und 2 wahr. Daraus folgt, dass A<void>::pointer
void*
sein muss.
BEARBEITEN: Es gibt auch explizite Formulierungen in 20.1.5 / 4 (es gilt, was Standardcontainer über Allokatoren annehmen können):
Der typedef-Memberzeiger, const_pointer, size_type und difference_type muss sein T *, T const *, size_t und ptrdiff_t, jeweils.
Nein, nicht wirklich.
Es gibt eine Anforderung, dass A & lt; T & gt; :: Zeiger in A & lt; T & gt; :: const_pointer und A & lt; T & gt; :: void_pointer umwandelbar ist, aber das ist alles, was ich finden kann.
Ein & lt; void & gt; :: -Zeiger ist wahrscheinlich void*
, es sei denn, Sie haben etwas ausgefallenen Spezialspeicher.
Beachten Sie, dass selbst wenn ein union
benutzbar ist, würde ich immer noch keinen verwenden, vor allem weil Sie hier wahrscheinlich von einer Form der automatischen Speicherverwaltung profitieren könnten (damit Ihr contain nicht leckt), was ausgefallene Klassen erfordert .
Ich würde daher einen zweistufigen Ansatz empfehlen:
delete
) boost::variant
auf Ihren Zeigern Auf diese Weise haben Sie sowohl automatische Speicherverwaltung als auch compacity .
Tags und Links c++ language-lawyer allocator standard-library