"Slicing" in C++?
-
Hallo,
ich habe eine etwas "seltsame" Frage:
ich habe eine Funktion, die in etwa so aussieht:setHeights(const std::vector<IndexHeightPair>& values); // IndexHeightPair sieht in etwa so aus: struct IndexHeightPair { int index; float height; };
Die Funktion erwartet also einen Vektor mit Strukturen, wobei jede Struktur ein Index/Höhen Pärchen ist.
Ich muss nun für alle Indices ZWEI Höhenwerte speichern (den ursprünlichen und modifizierten). Meine Datenstruktur zum Speichern sieht also so aus:struct IndexHeightPairStorage { int index; float initialheight; float modifiedHeight; };
Meine Datenstruktur ist also sowas: std::vector<IndexHeightPairStorage> foo; Es soll nun setHeights() aufgerufen werden und abhängig von bestimmten Parametern einmal mit den initialHeights und einmal mit den modifiedHeights. In Pseudocode also das:
std::vector<IndexHeightPairStorage> foo; // Datenstruktur if( useInitialHeights ) { setHeights(foo); // Hier soll setHeights mit foo aufgerufen werden (geht so natürlich nicht, da setHeights einen Vektor // mit einer Struktur erwartet, die nur EINEN Höhenwert hat). Ich bräuchte hier // so eine Art slicing die sagt: Übergeb für jede Struktur nur initialHeight */ } else setHeights(foo); // Hier soll bei jeder Struktur nur modifiedHeight übergeben werden
Kann man so ein "Struktur" Slicing irgendwie in C++ nachbauen?
-
Mit ein bisschen tricksen geht das
template<typename T> void setHeights(std::vector<T> const &v, float (T::*get) = &T::height) { // ... float const height = v[i].*get; // ... } // ... std::vector<IndexHeightPair> v; setHeights(v); std::vector<IndexHeightPairStorage> v; setHeights(v, &IndexHeightPairStorage::modifiedHeight);
-
Das Interface von setHeights zu ändern halte ich in dem Fall für fragwürdig. Eher sowas in der Art:
IndexHeightPair getInitial(IndexHeightPairStorage const& ihps) { IndexHeightPair ihp; ihp.index = ihps.index; ihp.height = ihps.initialHeight; return ihp; } IndexHeightPair getModified(IndexHeightPairStorage const& ihps); int main() { std::vector<IndexHeightPairStorage> storages; /* ... */ std::vector<IndexHeightPair> pairs; if (useInitialHeights) std::transform(storages.begin(), storages.end(), std::back_inserter(pairs), &getInitial); else std::transform(storages.begin(), storages.end(), std::back_inserter(pairs), &getModified); setHeights(pairs); }
-
Danke euch beiden.
Nur eines versteh ich nicht bei pumuckls Idee: Wieso ein back_inserter? Dann stehen doch in pairs die Werte von storages in umgekehrter Reihenfolge?
-
slicer schrieb:
Nur eines versteh ich nicht bei pumuckls Idee: Wieso ein back_inserter? Dann stehen doch in pairs die Werte von storages in umgekehrter Reihenfolge?
Nein. back_inserter liefert einen Iterator, der mit push_back die elemente in den (vorher leeren) reinstopft.