Container generisch verarbeiten



  • Hallo,
    ich würde gerne Container möglichst generisch verarbeiten. Beispiel: std::vector und QVector. Genauso std::map und std::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 Methode cbegin() 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. 🙂


Anmelden zum Antworten