std::copy mit Werten aus einer struct



  • Hallo,

    ich bin gerade zu blöd dafür:

    Wenn ich statt 'passende' vectors kopiere, wie hier:

    vector<int> src = { 1, 2, 3 }; 
    vector<int> dest = { 4, 5, 6 }; 
    
    std::copy(src.begin(), src.end(), std::back_inserter(dest)); 
    

    wie mache ich das, wenn die zu kopierenden Werte noch gekapselt sind, also so

    struct s
    {
    int i;
    };
    vector<s> src = { {1}, {2}, {3} }; 
    vector<int> dest = { 4, 5, 6 }; 
    
    std::copy(src.begin(), src.end(), std::back_inserter(dest));  // ?
    

    Also in schön und nicht über eine for-Schleife?



  • guck dir std::transform an.


  • Mod

    So direkt geht das nicht, da aus sicht von C++ s und int gänzlich inkompatible Typen sind. Nun gibt es zwei Ansätze:

    1. Der schnöde technische Ansatz, wenn es dir nur um die richtige Syntax geht. Du brauchst halt etwas, das dir dein s in einen int auspackt und in den Zielvector schreibt. Hier böte sich ein kurzes lambda an: std::for_each(src.begin(), src.end(), [&dest](s val){dest.push_back(val.i);});.
      Warum habe ich for_each und nicht copy benutzt? Weil copy einen ausgewachsenen Outputiterator erwartet, inklusive solcher Dinge wie einem Member value_type. Das kann man nicht mehr in eine kurze Zeile schreiben.
    2. Ansatz über das Datenmodell. Bin ich ein Fan von. Es ist hier zwar ein akademisches Beispiel, aber im echten Leben wäre die Frage doch jetzt, wieso jemand ein s in einen int konvertiert haben möchte, wenn die Modellierung von s doch ausdrückt, dass es mit int nichts zu tun hat. Also ist das entweder ein Logikfehler seitens des Programmierers, der hier inkompatible Objekte ineinander überführen will, oder das Datenmodell ist falsch (oder Möglichkeit 3: Das Modell ist richtig und der Programmierer ist sich der Gefahr bei der Umwandlung bewusst, will es aber trotzdem aus Günden. Aber für gefährliche Konvertierungen gibt es ein besseres Sprachmittel, nämlich den reinterpet_cast). Wenn das Modell von s falsch ist, als das eine Konvertierung nach int ausdrücklich erlaubt sein soll, dann sollte man diese auch anbieten (z.B. operator int() const {return i;}). Dann funktioniert auch das copy direkt und ohne Änderung, denn dann ist das ja eine ganz logische und sichere Operation.


  • @Bashar
    Du meinst erst transformieren und dann copy oder?
    Nee,das gefällt mir nicht; da scheint mir eine Schleife besser lesbar.

    @SeppJ
    Gut zu wissen, dass ich da zumindest nichts offensichtliches übersehen habe.

    Falls es dich interessiert: S ist eine grosse Datenklasse ; S.i und dest sind IDs.
    dest (also die IDs) sind ein Parameter und in der Funktion werden die Ss entsprechend behalten, geladen oder gelöscht.

    Danke für die Ratschläge.



  • @Jockelx Ach Kind

    #include <vector>
    #include <algorithm>
    #include <iostream>
    
    using namespace std;
    
    int main()
    {
        struct s
        {
    	int i;
        };
        vector<s> src = { {1}, {2}, {3} }; 
        vector<int> dest = { 4, 5, 6 };
    
        transform(begin(src), end(src), back_inserter(dest), [](auto& v ) { return v.i; } );
    
        for( auto i: dest ) cout << i << " ";
        cout << "\n";
    }
    
    


  • @Jockelx sagte in std::copy mit Werten aus einer struct:

    @Bashar
    ...

    std::transform(src.begin(), src.end(), std::back_inserter(dest), [](auto& s) { return s.i; });



  • @Bashar
    Ja, klar, dumme Frage.


  • Mod

    @Jockelx sagte in std::copy mit Werten aus einer struct:

    @Bashar
    Du meinst erst transformieren und dann copy oder?
    Nee,das gefällt mir nicht; da scheint mir eine Schleife besser lesbar.

    Nein, er meint so wie ich das gemacht habe mit for_each. Die Unterschiede zwischen transform und for_each (und auch map) sind ziemlich fein und es geht eher darum, was man inhaltlich damit ausdrücken möchte. Hier wäre nach allem was du sonst so gesagt hast, transform wahrscheinlich die bessere Wahl

    Falls es dich interessiert: S ist eine grosse Datenklasse ; S.i und dest sind IDs.

    Dann passt das Datenmodell, aber deine ursprüngliche Frage hat einen völlig falschen Eindruck erweckt.


Anmelden zum Antworten