Problem mit pair und vector


  • Mod

    Kleine Kritik:

    for (unsigned long i = computed_orders.size(); i < order; ++i) {
                    computed_orders.push_back(0);
                    map_order_to_index.push_back(-1);
                }
    

    ➡

    computed_orders   .resize( order, 0 );
    map_order_to_index.resize( order, std::numeric_limits<unsigned int>::max() ); // Edit: Ist die zweite Zeile auch korrekt? Ist die Größe von map_order... dieselbe wie die von computed_orders?
    

    _________________________________________________________________________

    nodes.push_back(new_nodesAndWeights.first);
    weights.push_back(new_nodesAndWeights.second);
    

    Falls möglich umschreiben zu

    nodes  .push_back( std::move(new_nodesAndWeights.first ) );
    weights.push_back( std::move(new_nodesAndWeights.second) );
    

    _________________________________________________________________________

    pair<vector<double>*, vector<double>* > nodesAndWeights_forOrder;
        nodesAndWeights_forOrder.first = &nodes[order];
        nodesAndWeights_forOrder.second = &weights[order];
    
        return nodesAndWeights_forOrder;
    

    ➡

    return {&nodes[order], &weights[order]};
    


  • Danke Arcoth, das ist natürlich eleganter! Übernehme ich sofort!

    Nachdem ich den Post abgeschickt habe hat's keine 5 Minuten mehr gedauert:

    Ich Idiot hab' falsch auf die Daten zugegriffen. Richtig ist:

    nodesAndWeights_forOrder.first = &nodes[map_order_to_index[order]];
        nodesAndWeights_forOrder.second = &weights[map_order_to_index[order]];
    

    Witzig, dass sich der Compiler nicht beschwert hat (-Wall -pedantic), und trotzdem an erster Stelle das richtige Ergebnis stand.

    Sorry Dafür!


  • Mod

    Wäre es nicht zweckmäßig, Knoten und Gewichte zusammen zu speichern?

    vector< vector< pair< double, double > > >  weighted_nodes;
    // oder wenigstens
    vector< pair< vector< double >, vector< double > > >  weighted_nodes;
    

    Der gesamte if-Zweig sollte in einer eigenen Funktion stehen. Dann wird das Ganze übersichtlicher.

    nodes  .push_back( std::move(new_nodesAndWeights.first ) );
    weights.push_back( std::move(new_nodesAndWeights.second) );
    

    andere Variante wäre hier mal tie zu verwenden:

    nodes.push_back( {} );
    weights.push_back( {} );
    tie( nodes.back(), weights.back() ) = compute_nodesAndWeights_gaussLobattoQuadrature(order);
    

    (mit weighted_nodes wird es noch einfacher).

    EIn Rückgabetyp

    pair<vector<double>&, vector<double>& >
    

    könnte syntaktisch bequemer sein. Dann ist nämlich zum Beispiel der Zugriff etwa auf den Indexoperator der Vectoren direkt möglich, sonst erfordert die extra Derenzierung zusätzlichen Schreibaufwand.



  • Hi Camper,
    das mit dem Rückgabetyp ist ein guter Einwand!

    tie hab' ich bisher noch nie wirklich genutzt, die Doku dazu sieht aber vielversprechend aus für das, was ich eigentlich suche.

    Mein erster Versuch für die Klasse war mit deinem zweiten Vorschlag:

    vector< pair< vector< double >, vector< double > > >  weightsAndNodes;
    

    Da hab' ich aber eben mit den Rückgabetypen was nicht hin bekommen:

    Angenommen ich nehme das Format oben.
    Was ist denn dann mein Rückgabetyp??
    Das hier:

    pair < vector < double > , vector < double > >&
    

    ?
    Sorry, aber bei sowas bin ich immer total hilflos..

    Danke für eure Hilfe!


  • Mod

    denis2102 schrieb:

    Angenommen ich nehme das Format oben.
    Was ist denn dann mein Rückgabetyp??
    Das hier:

    pair < vector < double > , vector < double > >&
    

    Genau (pair < vector < double >&, vector < double >& >) würde allerdings auch funktionieren.

    Die Berechnung wird dann einfach zu

    weightsAndNodes.emplace_back( compute_nodesAndWeights_gaussLobattoQuadrature(order));
    


  • Danke für deine Tipps!
    Ich habe das mit den Rückgabetypen nicht so richtig hinbekommen, und werde die Infos jetzt einfach als 2 2d-Vektoren speichern. So eine große Rolle spielt das ja nicht.

    Die Rückgabefunktion sieht jetzt so aus, und funktioniert:

    pair < vector<double>&, vector<double>& > Computation_Safe::get_nodesAndWeights_forOrder(unsigned int order)
    {
        resize_ifNecessary(order); // Berechnet auch Gewichte und Knoten falls nötig
        return { nodes[map_order_to_index[order]],weights[map_order_to_index[order]] };
    }
    

    1. Frage: Der Tipp mit den geschweiften Klammern kam von euch aus dem Forum. Was genau macht das?

    2. Frage: Kann mir jemand erklären wie ich denn jetzt den Rückgabetyp mit make_pair (theoretisch) angeben könnte??

    return make_pair(nodes[map_order_to_index[order]],weights[map_order_to_index[order]]
    

    bringt mir nur ein 'no viable conversion from [...] to [...]'.

    EDIT: Wenn ich die Arbeit abgebe, muss ich das auf jeden Fall noch umschreiben. Die Version mit den geschweiften Klammern kompiliert problemlos in xCode, aber nur unter Verwendung vom LLVM Compiler. Sowohl G++ als auch CLANG bekommen das (aus dem Terminal) nicht kompiliert.

    Liebe Grüße,
    Denis


  • Mod

    denis2102 schrieb:

    bringt mir nur ein 'no viable conversion from [...] to [...]'.

    was genau in den [...] steht, würde uns da schon interessieren.

    denis2102 schrieb:

    Die Version mit den geschweiften Klammern kompiliert problemlos in xCode, aber nur unter Verwendung vom LLVM Compiler. Sowohl G++ als auch CLANG bekommen das (aus dem Terminal) nicht kompiliert.

    -std=c++0x oder -std=c++11 mit angeben



  • Die komplette Fehlermeldung ist

    No viable conversion from 'pair<typename __make_pair_return<class vector<double, class allocator<double> > &>::type, typename __make_pair_return<class vector<double, class allocator<double> > &>::type>' to 'pair<vector<double> &, vector<double> &>'
    

    Das mit -std=C++** funktioniert dabei auch nicht.

    Was macht denn jetzt die geschweifte Klammer?

    Verzeiht meine Ratlosigkeit 🙄


  • Mod

    stimmt, müsste

    return make_pair(std::ref(nodes[map_order_to_index[order]]),std::ref(weights[map_order_to_index[order]]));
    

    lauten und braucht dann auch C++11. In C++03 bleibt dir nichts anderes übrig, als den Rückgabetypen direkt beim return nochmal hinzuschreiben.


  • Mod

    @camper:

    nodes.push_back( {} );
    weights.push_back( {} );
    

    Hier sollte wohl eher emplace_back ohne Argumente stehen.

    weightsAndNodes.emplace_back( compute_nodesAndWeights_gaussLobattoQuadrature(order));
    

    Und hier sollte push_back stehen.

    Noch kürzer geht es auch

    tie( *back_inserter(nodes), *back_inserter(weights) ) = compute_nodesAndWeights_gaussLobattoQuadrature(order);
    

    Was genau macht das?

    Das nennt sich list-initialization; hier speziell copy-list-initialization. Es übergibt - grob beschrieben - die Listenelemente als Konstruktorargumente an das Rückgabeobjekt.


  • Mod

    Arcoth schrieb:

    tie( *back_inserter(nodes), *back_inserter(weights) ) = compute_nodesAndWeights_gaussLobattoQuadrature(order);
    

    interessante Idee.


Anmelden zum Antworten