Die Implementierung von Vergleichsoperatoren über 'Tupel' und 'Band', eine gute Idee?
(Hinweis: tuple
und tie
genommen werden kann, die von Boost und C++11.)
Beim schreiben von kleinen Strukturen mit nur zwei Elementen, die ich manchmal dazu neigen, wählen Sie eine std::pair
, wie alle wichtigen Dinge bereits erledigt, die für diesen Datentyp, wie operator<
für strengen-schwach-Bestellung.
Die Nachteile sind jedoch die ziemlich nutzlos Variablen-Namen. Auch wenn ich selbst erstellt, die typedef
wird, werde ich mich nicht daran erinnern, 2 Tage später, was first
und was second
genau war, vor allem, wenn Sie beide vom selben Typ sind. Dies wird noch schlimmer, wenn mehr als zwei Mitglieder, als Schachteln pair
s ziemlich viel saugt.
Die andere option ist, liegt tuple
entweder von Boost und C++11, aber nicht wirklich Aussehen schöner und klarer. Also gehe ich zurück zu dem schreiben der struct selbst, einschließlich eventuell benötigter Vergleich Betreiber.
Da vor allem die operator<
können sehr umständlich, ich dachte, der Umgehung dieser ganze Schlamassel nur durch die Berufung auf die Operationen definiert, die für tuple
:
Beispiel operator<
z.B. für strengen-schwach-Bestellung:
bool operator<(MyStruct const& lhs, MyStruct const& rhs){
return std::tie(lhs.one_member, lhs.another, lhs.yet_more) <
std::tie(rhs.one_member, rhs.another, rhs.yet_more);
}
(tie
macht einen tuple
von T&
Hinweise aus der übergebenen Argumente.)
Bearbeiten: Der Vorschlag von @DeadMG an privat Erben von tuple
ist nicht schlecht, aber es hat einige Nachteile:
- Wenn die Betreiber frei stehen (eventuell Freunden), die ich brauche, um zu Erben öffentlich
- Mit casting, meine Funktionen /Operatoren (
operator=
speziell) können leicht umgangen werden - Mit der
tie
Lösung, kann ich dann bestimmte Mitglieder, wenn Sie nicht wichtig für die Bestellung
Gibt es irgendwelche Nachteile bei dieser Implementierung, dass ich beachten muss?
- Perfekt sieht mir vernünftig...
- Das ist eine sehr clevere Idee, auch wenn es nicht pan out. Ich bin zu haben, um das zu prüfen.
- Das sieht ziemlich vernünftig. Die einzige Gefahr, die ich gerade denke, ist, dass
tie
kann nicht angewendet werden, um bit-Feld der Mitglieder. - Schade gibt es nicht eine Art von Selbstbeobachtung, so dass Sie tun können, diese automatisch für jede Klasse - also haben die Standard-Vergleichsoperatoren. Die Band-trick ist cool, aber.
- Ich mag diese Idee! Wenn die
tie(...)
Anrufe gehen, dupliziert werden in unterschiedlichen Operatoren (=, ==, <, etc.) Sie schreiben konnte, ein eigenes inline-Methodemake_tuple(...)
zu Kapseln und dann rufen Sie es von den verschiedenen anderen Orten, wie inreturn lhs.make_tuple() < rhs.make_tuple();
(obwohl der Rückgabetyp von dieser Methode könnte sein, Spaß zu erklären!) - C++14 ist die Rettung!
auto tied() const{ return std::tie(the, members, here); }
Du musst angemeldet sein, um einen Kommentar abzugeben.
Dies ist sicher gehen, um es einfacher zu schreiben, einen richtigen Betreiber als rollierende es selbst. Ich würde sagen, nur in Betracht ziehen, einen anderen Ansatz, wenn profiling zeigt den Vergleich Vorgang zu einem zeitaufwändigen Teil Ihrer Anwendung. Andernfalls wird die einfache Pflege dieses sollte schwerer Wiegen als mögliche Leistung betrifft.
tuple<>
'soperator<
wäre langsamer als ein handschriftlich ein.Komme ich auf das gleiche problem und meine Lösung nutzt c++11 variadic templates. Hier kommt der code:
Den .h Artikel:
Und die .cpp für die base-case ohne Argumente:
Nun Ihrem Beispiel wird zu:
Meiner Meinung nach bist du immer noch nicht Adressierung das gleiche Problem wie die
std::tuple
löst - nämlich, müssen Sie wissen, wie viele und die Namen der einzelnen member-variable, Sie duplizieren es zweimal in der Funktion. Sie könnten entscheiden Sie sich fürprivate
Vererbung.Dieser Ansatz ist ein wenig bisschen mehr von einem Durcheinander zu beginnen, aber Sie sind nur die Aufrechterhaltung der Variablen und Namen in einem Ort, anstatt in jedem Ort für jeden Bediener, die Sie wünschen zu überlasten.
T& one_member(){ return std::get<0>(*this); }
etc? Aber hieße das nicht, müssen Sie mir, eine solche Methode für jedes "Mitglied" habe ich, einschließlich überladungen für const und non-const-version?Wenn Sie planen, verwenden Sie mehr als einen operator überladen, oder mehr Methoden aus dem Tupel, würde ich empfehlen, Tupel ein Mitglied der Klasse oder Ableitung von Tupel. Ansonsten, was du tust, ist viel mehr Arbeit. Bei der Entscheidung zwischen den beiden, eine wichtige Frage zu beantworten ist: wollen Sie Ihre Klasse auf werden ein Tupel? Wenn nicht würde ich empfehlen, mit einem Tupel und die Beschränkung der Schnittstelle durch die Verwendung von delegation.
Konnten Sie erstellen Zugriffsmethoden auf "umbenennen" die Mitglieder der Tupel.
operator<
mitstd::tie
vernünftig?" Ich verstehe nicht, wie diese Antwort bezieht sich auf diese Frage.