Frage

Wie die meisten Programmierer Ich bewundere und versuchen, die Prinzipien der Literate Programmierung zu folgen, aber in C ++ ich mich routinemäßig finden std::pair verwenden, für eine Unmenge gemeinsame Aufgaben. Aber std::pair ist, meiner Meinung nach, ein abscheulicher Feind der gebildeten Programmierung ...

Mein Punkt ist, wenn ich wieder zu Code komme ich einen oder zwei Tage vor geschrieben habe, und ich sehe Manipulationen eines std::pair (in der Regel als Iterator) ich mich fragen, „ was hat ITER> erster und ITER> Sekunde bedeuten ??? “.

Ich vermute, andere die gleichen Zweifel haben, wenn sie bei ihrem std::pair Code suchen, so dass ich frage mich, habe mit einigen guten Lösungen jemand kommen Alphabetisierung zu erholen, wenn std::pair mit?

War es hilfreich?

Lösung

Wie wäre es damit:

struct MyPair : public std::pair < int, std::string >
{
    const int& keyInt() { return first; }
    void keyInt( const int& keyInt ) { first = keyInt; }
    const std::string& valueString() { return second; }
    void valueString( const std::string& valueString ) { second = valueString; }
};

Es ist ein bisschen ausführliches, aber dies in Ihrem Code verwenden könnte die Dinge ein wenig leichter lesbar machen, zum Beispiel:

std::vector < MyPair > listPairs;

std::vector < MyPair >::iterator iterPair( listPairs.begin() );
if ( iterPair->keyInt() == 123 )
    iterPair->valueString( "hello" );

Andere als diese, ich kann keine silberne Kugel sehen, dass die Dinge machen geht zu viel klarer.

Andere Tipps

std::pair ist ein guter Weg, um einen „lokalen“ und im Wesentlichen anonymen Typen mit im wesentlichen anonymen Spalten zu machen; wenn Sie ein bestimmtes Paar über eine so großen lexikalischen Raum, die Sie den Typen und die Spalten zu nennen brauchen, würde ich stattdessen eine einfache struct verwenden.

typedef std::pair<bool, int> IsPresent_Value;
typedef std::pair<double, int> Price_Quantity;

... Sie erhalten den Punkt.

Sie können zwei Paare von Getter (const und nicht) erstellen, die lediglich einen Verweis auf erste zurückkehren wird und zweitens, aber viel besser lesbar sein. Zum Beispiel:

string& GetField(pair& p) { return p.first; }
int& GetValue(pair& p) { return p.second; }

Werden Sie die Feld- und Werte Mitglieder aus einem gegebenen Paar lassen, ohne welches Mitglied mit sich zu erinnern, was hält.

Wenn Sie erwarten, dass diese viel verwenden, können Sie auch ein Makro erstellen, die diese Getter für Sie generiert werden, da die Namen und Typen: MAKE_PAIR_GETTERS (Field, String, value, int) oder so. Macht die Getter einfach wird wahrscheinlich die Compiler erlauben sie weg zu optimieren, so dass sie keinen Overhead zur Laufzeit hinzufügen werden; und das Makro wird es ein Kinderspiel, diese Getter zu schaffen, was auch immer verwenden Sie machen von Paaren.

Sie könnten boost Tupeln verwenden, aber sie nicht wirklich das zugrunde liegende Problem ändern: Haben Ihre wirklich jeder Teil des Paares / Tupel mit einem kleinen integrierten Typ zugreifen möchten, oder möchten Sie mehr ‚lesen und schreiben‘ Code. Siehe diese Frage ich eine Weile zurück geschrieben.

Allerdings boost :: optional ist ein nützliches Werkzeug, das ich gefunden habe, ersetzt eine ganze Reihe von Fällen, in denen Paare / Tupel als ther Antwort propagiert werden.

Vor kurzem habe ich finde ich boost::tuple als Ersatz für std::pair verwenden. Sie können für jedes Mitglied Aufzählungen definieren und es ist so offensichtlich, was jedes Mitglied ist:

typedef boost::tuple<int, int> KeyValueTuple;
enum {
  KEY
  , VALUE
};

void foo (KeyValueTuple & p) {
    p.get<KEY> () = 0;
    p.get<VALUE> () = 0;
}

void bar (int key, int value)
{
  foo (boost:tie (key, value));
}

BTW, Kommentare willkommen auf, wenn es ein versteckt Kosten ist, diesen Ansatz zu verwenden.

EDIT: Entfernen Namen von globalem Bereich

.

Nur eine kurze Bemerkung zu globaler Namespace. Im Allgemeinen würde ich verwenden:

struct KeyValueTraits
{
  typedef boost::tuple<int, int> Type;
  enum {
    KEY
    , VALUE
  };
};

void foo (KeyValueTuple::Type & p) {
    p.get<KeyValueTuple::KEY> () = 0;
    p.get<KeyValueTuple::VALUE> () = 0;
}

Es sieht der Fall zu sein, die boost::fusion näher zusammen die Identität und den Wert tut binden.

Wie Alex erwähnt, std::pair sehr bequem ist, aber wenn es verwirrend wird eine Struktur erstellen und sie auf die gleiche Art und Weise zu nutzen, müssen Sie einen Blick auf std::pair Code, es ist nicht so komplex.

Ich mag std nicht :: pair entweder in std :: map verwendet, Karte Einträge Mitglieder Schlüssel und Wert gehabt haben sollte.
Ich selbst boost :: MIC diese verwendet zu vermeiden. Allerdings boost :: MIC kommt auch mit Kosten verbunden.

Auch ein std :: pair Ergebnisse in weniger als lesbarem Code Rückkehr:

if (cntnr.insert(newEntry).second) { ... }

???

Ich fand auch, dass std :: Paar gemeinsam von den faulen Programmierern, die zwei Werte benötigt wird verwendet, aber nicht denken, warum diese Werte, bei denen zusammen benötigt werden.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top