Container generisch verarbeiten
-
Hallo,
ich würde gerne Container möglichst generisch verarbeiten. Beispiel:std::vector
undQVector
. Genausostd::map
undstd::unorderd_map
.Ich habe hierfür folgendes programmiert:
#include <iostream> #include <vector> #include <map> template <template <typename> class T1, typename T2> auto print(const T1<T2> &vec) -> decltype(vec.cbegin(), void()) { auto begin = vec.cbegin(); auto end = vec.cend(); for (auto it = begin; it != end; ++it) { std::cout << *it << std::endl; } } template <template <typename, typename> class T1, typename Key, typename Value> auto print(const T1<Key, Value> &vec) -> decltype(vec.cbegin()->first, vec.cbegin()->second, void()) { auto begin = vec.cbegin(); auto end = vec.cend(); for (auto it = begin; it != end; ++it) { std::cout << "Key: "<< it->first << ". Value: " << it->second << std::endl; } } int main(int, char**) { std::vector<int> vec { 1, 2, 3 }; print(vec); std::map<int, double> map {{1, 1.5}}; print(map); }
Das funktioniert wunderbar mit dem GGC, aber clang sagt, dass es keine passenden Kandidaten gefunden hat.
Ich würde das gerne unter C++ 17 entwickeln.Bin über Anregungen und Tipps dankbar.
PS: Mein Ziel ist es nicht den Stream-Operator zu überladen. Solche Lösungen habe ich schon im Internet gefunden. Diese Lösung ist mir nicht generisch genug.
-
std::vector hat ja eigentlich 2 Template-Parameter (auch wenn der 2. einen Standardwert hat), also Godbolt: Clang & gcc-Compiler.
Gleiches dann auch für
std::map<...>
.PS: Warum hast du eigentlich bei
decltype(...)
die unnötigen Ausdrücke stehen?
-
Gibt es einen Grund, warum du nicht einfach zwei Iteratoren als Parameter nimmst?
-
@Th69 sagte in Container generisch verarbeiten:
std::vector hat ja eigentlich 2 Template-Parameter (auch wenn der 2. einen Standardwert hat), also Godbolt: Clang & gcc-Compiler.
Gleiches dann auch für
std::map<...>
.Mist, das ist dann nicht mehr mit Qt kompatibel.
PS: Warum hast du eigentlich bei
decltype(...)
die unnötigen Ausdrücke stehen?Das ist ein Filter und soll bewirken, dass die Container die richtigen Funktionen wählen. Bspw. hat
std::map
ebenfalls die Methodecbegin()
und das kann zu Mehrdeutigkeiten führen und der Compiler meckert dann.
-
@wob sagte in Container generisch verarbeiten:
Gibt es einen Grund, warum du nicht einfach zwei Iteratoren als Parameter nimmst?
Ich finde das persönlich sehr ungemütlich. Das soll letztendlich auf eine Serialisierungs-Funktion hinauslaufen, in denen Member-Variablen serialisiert werden sollen. Man möchte in so ziemlich 100 % der Fällen einen Container vollständig serialisieren, deshalb ist es komfortabler in dem man einfach eine Member-Variable übergibt.
Evtl. könnte ich aber den Weg über Iteratoren über Umwege nutzen, sodass der Nutzer der Schnittstelle davon nichts hinbekommt. Von daher: Danke, für die Anregung.