Maps
-
feinschmecker schrieb:
Hacker schrieb:
this->ist völlig unnötig.Geschmackssacke.
Aber kein Muss. Deswegen ist die Aussage "da muss noch ein this-> hin" falsch.
-
Ob this oder nicht, das ist ja hier jetzt nicht das Problem

-
Hacker schrieb:
feinschmecker schrieb:
Hacker schrieb:
this->ist völlig unnötig.Geschmackssacke.
Aber kein Muss. Deswegen ist die Aussage "da muss noch ein this-> hin" falsch.
Gegenteiliges hab ich auch nie behauptet. Ich hab nur gesagt, dass da ein "this->" fehlt, was ich auf meinen Beitrag bezogen hab, weil ich es ein mal hin geschrieben und beim anderen aus Versehen vergessen hab.
-
Gut gut, schon verstanden. Zurück zum Thema - oder besser gesagt zu seinem Code.
-
Schön

Der, falls es nicht bemerkt wurde, bereits gepostet wurde
-
Jo, du inkludierst natürlich nicht
<iostream>.
Vergiss übrigens nicht, dass beide Maps in MapDictionary unabhängig von einander existieren.
-
Ja, hatte es mit Map schon bemerkt..
Danke, natürlich war es (mal wieder) iostream.

-
KeinNameMehrFrei schrieb:
Brauch es auch nur für int und String.
Ich hab 4 Fälle:
<int, string>
<string, int>
<string, string>
<int, int>Jetzt würde mich dochmal die Aufgabenstellung interessieren.
-
Theoretisch würde ich sowas nehmen:
template<typename key1T, typename key2T> struct bimap { typedef std::vector<std::pair<key1T, key2T>> array_type; array_type array; typename array_type::iterator find(key2T tof) { typename array_type::iterator iter = array.begin(); for(;iter != array.end();++iter) if(iter->second == tof) break; return iter; } typename array_type::iterator find(key1T tof) { typename array_type::iterator iter = array.begin(); for(;iter != array.end();++iter) if(iter->first == tof) break; return iter; } key1T& operator[](key2T a) { typename array_type::iterator iter; if((iter = find(a)) != array.end()) return iter->first; array.push_back(std::make_pair(key1T(), a)); return array.back().first; } key2T& operator[](key1T a) { typename array_type::iterator iter; if((iter = find(a)) != array.end()) return iter->second; array.push_back(std::make_pair(a, key2T())); return array.back().second; } };Nur ist halt das Problem, dass es nicht reguläre Memberfunktionen wie in einer
std::mapgibt...

Aufgabe für heute gefunden!
-
.. und das es ziemlich langsamer pfusch ist..

-
daki schrieb:
.. und das es ziemlich langsamer pfusch ist..

Na wenn du das gleich so sagst... machs besser ( :Herausforderung: )

Ich bin soweit fertig (unimplementierte Funktionen sind ja durch das Set verfügbar, und da das nur ein Wrapper um ein Set ist...).
template<typename leftKeyT, typename rightKeyT> class bimap { public: typedef std::pair<leftKeyT, rightKeyT> value_type; typedef std::set<value_type> array_type; array_type mSet;///Internal array (set) typedef leftKeyT left_key_type; typedef rightKeyT right_key_type; typedef typename array_type::iterator iterator; typedef typename array_type::const_iterator const_iterator; typedef typename array_type::size_type size_type; //Hier können theoretisch noch andere typedefs hin, aber die sind durch das Set verfügbar iterator find(rightKeyT const& tof) { return find(tof); } iterator find(leftKeyT const& tof) { return find(tof); } const_iterator find(rightKeyT const& tof) const { return std::find_if(mSet.begin(), mSet.end(), [&](value_type const& a){return a.second == tof;}); } const_iterator find(leftKeyT const& tof) const { return std::find_if(mSet.begin(), mSet.end(), [&](value_type const& a){return a.first == tof;}); } leftKeyT& operator[](rightKeyT const& a) { return const_cast<leftKeyT&>(insert(a).first->first); } rightKeyT& operator[](leftKeyT const& a) { return const_cast<rightKeyT&>(insert(a).first->second); } void clear() { mSet.clear(); } size_type count(leftKeyT const& lK) const { return std::count_if(mSet.mSet.begin(), mSet.end(), [&](std::pair<leftKeyT, rightKeyT> const& p) { return p.first == lK; }); } size_type count(rightKeyT const& rK) const { return std::count_if(mSet.mSet.begin(), mSet.end(), [&](std::pair<leftKeyT, rightKeyT> const& p) { return p.second == rK; }); } size_type erase(rightkeyT const& lK) { size_type rval = count(lK); std::remove_if(mSet.begin(), mSet.end(), [&](value_type const& p){return p.second == lK;}); return rval; } size_type erase(leftkeyT const& lK) { size_type rval = count(lK); std::remove_if(mSet.begin(), mSet.end(), [&](value_type const& p){return p.first == lK;}); return rval; } template<typename keyT> std::pair<iterator, bool> insert(keyT const& t) { std::pair<iterator, bool> rval(find(t), false); if(rval.first != mSet.end()) return rval; return mSet.insert(std::make_pair(leftKeyT(), t));; } };
-
Hacker schrieb:
iterator find(rightKeyT const& tof) { return std::find_if(mSet.begin(), mSet.end(), [&](value_type const& a){return a.second == tof;}); } const_iterator find(rightKeyT const& tof) const { return const_cast<bimap*>(this)->find(tof); }Du kannst doch mit einer non-const Instanz eine const-Methode aufrufen.
-
Gugelmoser schrieb:
Hacker schrieb:
iterator find(rightKeyT const& tof) { return std::find_if(mSet.begin(), mSet.end(), [&](value_type const& a){return a.second == tof;}); } const_iterator find(rightKeyT const& tof) const { return const_cast<bimap*>(this)->find(tof); }Du kannst doch mit einer non-const Instanz eine const-Methode aufrufen.
Ja und dann? Findests schöner, oder? Ich bin aber zu faul zum editieren

-
Hacker schrieb:
Ja und dann? Findests schöner, oder? Ich bin aber zu faul zum editieren

Ist nicht alles, das keinen
const_casthat, schöner?
-
Hacker schrieb:
Gugelmoser schrieb:
Hacker schrieb:
iterator find(rightKeyT const& tof) { return std::find_if(mSet.begin(), mSet.end(), [&](value_type const& a){return a.second == tof;}); } const_iterator find(rightKeyT const& tof) const { return const_cast<bimap*>(this)->find(tof); }Du kannst doch mit einer non-const Instanz eine const-Methode aufrufen.
Ja und dann? Findests schöner, oder? Ich bin aber zu faul zum editieren

Die Implementation einer non-const Überladung über die const-Überladung ist trivialerweise korrekt, sofern der Rückgabewert kompatibel ist - das ist eine Frage des Contracts.
Der umgekehrte Weg funktioniert dagegen nur, falls die non-const Variante das Objekt tatsächlich nicht verändert - ist also von deren Implementation abhängig.
Preisfrage: Welche Variante koppelt die Funktionen weniger stark und ist folglich vorzuziehen?
-
camper schrieb:
Der umgekehrte Weg funktioniert dagegen nur, falls die non-const Variante das Objekt tatsächlich nicht verändert - ist also von deren Implementation abhängig.
Die Bedingungen des umgekehrten Weges sind mir gekannt. Deswegen habe ich es ja auch nicht verändert. Aber wenn ihr darauf besteht

-
camper schrieb:
Preisfrage: Welche Variante koppelt die Funktionen weniger stark und ist folglich vorzuziehen?
Ich würde die Variante ohne
const_castnehmen, aber nur aus dem Grund, weil ichconst_castnicht schön finde. Aber ich bin auf deine Erklärung gespannt, camper.
-
camper schrieb:
Preisfrage: Welche Variante koppelt die Funktionen weniger stark und ist folglich vorzuziehen?
Die Koppelung ist doch vollkomen egal. Es geht um Sicherheit gegenüber Änderungen - und die ist nur bei non-const über const gegeben, folglich ist diese vorzuziehen.
Gugelmoser schrieb:
Ich würde die Variante ohne
const_castnehmen, aber nur aus dem Grund, weil ichconst_castnicht schön finde. Aber ich bin auf deine Erklärung gespannt, camper.
const_cast ist nicht per-se unschön.