In C ++ 14 scheinen sich assoziative Container von C ++ 11 geändert zu haben - [assoziativ.reqmts] / 13 sagt:
Die Mitgliedsfunktionsschablonen
find
,count
,lower_bound
,upper_bound
, undequal_range
darf nicht in die Überladungsauflösung teilnehmen , es sei denn die ArtCompare::is_transparent
vorhanden ist .
Was ist der Zweck, einen Komparator "transparent" zu machen?
C ++ 14 bietet auch Bibliotheksvorlagen wie diese:
template <class T = void> struct less {
constexpr bool operator()(const T& x, const T& y) const;
typedef T first_argument_type;
typedef T second_argument_type;
typedef bool result_type;
};
template <> struct less<void> {
template <class T, class U> auto operator()(T&& t, U&& u) const
-> decltype(std::forward<T>(t) < std::forward<U>(u));
typedef *unspecified* is_transparent;
};
So zum Beispiel, std::set<T, std::less<T>>
würde nicht einen transparenten Komparator, aber std::set<T, std::less<>>
würde eine haben.
Welches Problem löst dies und ändert sich dadurch die Funktionsweise von Standardcontainern? Zum Beispiel kann die Template - Parameter von std::set
immer noch Key, Compare = std::less<Key>, ...
, nicht so der Standardsatz verliert seine find
, count
usw. Mitglieder?
Antworten:
Siehe Dietmars Antwort und Remyabels Antwort .
Nein, nicht standardmäßig.
Mit den Überladungen der neuen Elementfunktionsvorlagen
find
usw. können Sie einen Typ verwenden, der mit dem Schlüssel des Containers vergleichbar ist, anstatt den Schlüsseltyp selbst zu verwenden. Siehe N3465 von Joaquín Mª López Muñoz für eine Begründung und einen detaillierten, sorgfältig geschriebenen Vorschlag, diese Funktion hinzuzufügen.Auf dem Treffen in Bristol stimmte die LWG zu, dass die heterogene Suchfunktion nützlich und wünschenswert war, aber wir konnten nicht sicher sein, dass Joaquins Vorschlag in allen Fällen sicher sein würde. Der N3465-Vorschlag hätte bei einigen Programmen ernsthafte Probleme verursacht (siehe Abschnitt Auswirkungen auf den vorhandenen Code ). Joaquín bereitete einen aktualisierten Entwurf eines Vorschlags mit einigen alternativen Implementierungen mit unterschiedlichen Kompromissen vor, was der LWG sehr hilfreich war, um die Vor- und Nachteile zu verstehen, aber alle riskierten, einige Programme auf irgendeine Weise zu brechen, sodass es keinen Konsens gab, die Funktion hinzuzufügen. Wir haben entschieden, dass es zwar nicht sicher ist, die Funktion unbedingt hinzuzufügen, aber sicher ist, wenn sie standardmäßig deaktiviert ist und nur "Opt-In" ist.
Der Hauptunterschied des N3657- Vorschlags (der in letzter Minute von mir und STL auf der Grundlage von N3465 und einem später unveröffentlichten Entwurf von Joaquín überarbeitet wurde ) bestand darin, den
is_transparent
Typ als Protokoll hinzuzufügen, mit dem die neue Funktionalität aktiviert werden kann.Wenn Sie keinen "transparenten Funktor" verwenden (dh einen, der einen
is_transparent
Typ definiert ), verhalten sich die Container genauso wie immer, und das ist immer noch die Standardeinstellung.Wenn Sie sich für die Verwendung
std::less<>
(die für C ++ 14 neu ist) oder einen anderen "transparenten Funktortyp" entscheiden, erhalten Sie die neue Funktionalität.Die Verwendung
std::less<>
von Alias-Vorlagen ist einfach:Der Name
is_transparent
stammt von STLs N3421, das C ++ 14 die "Diamantoperatoren" hinzufügte. Ein "transparenter Funktor" akzeptiert alle Argumenttypen (die nicht identisch sein müssen) und leitet diese Argumente einfach an einen anderen Operator weiter. Ein solcher Funktor ist genau das, was Sie für eine heterogene Suche in assoziativen Containern benötigen. Daher wurde der Typis_transparent
allen Diamantoperatoren hinzugefügt und als Tag-Typ verwendet, um anzugeben, dass die neue Funktionalität in assoziativen Containern aktiviert werden soll. Technisch gesehen benötigen die Container keinen "transparenten Funktor", sondern nur einen, der das Aufrufen mit heterogenen Typen unterstützt (z. B. ist derpointer_comp
Typ in https://stackoverflow.com/a/18940595/981959 gemäß der STL-Definition nicht transparent.pointer_comp::is_transparent
ermöglicht die Verwendung zur Lösung des Problems). Wenn Sie immer nurstd::set<T, C>
mit Schlüsseln vom Typ nachschlagenT
oderint
dannC
nur mit Argumenten vom TypT
undint
(in jeder Reihenfolge) aufrufbar sein müssen, muss es nicht wirklich transparent sein. Wir haben diesen Namen teilweise verwendet, weil wir keinen besseren Namen finden konnten (ich hätte es vorgezogen,is_polymorphic
weil solche Funktoren statischen Polymorphismus verwenden, aber es gibt bereits einstd::is_polymorphic
Typmerkmal, das sich auf dynamischen Polymorphismus bezieht).quelle
<>
den verknüpften Vorschlag, aber dieser Vorschlag wurde nicht eingeführt<>
- es ist eine vorhandene Syntax für eine leere Vorlagenparameterliste. "Diamond Operator Functors" wären etwas weniger verwirrend.In C ++ 11 sind nicht Mitglied Vorlagen
find()
,lower_bound()
usw. Das heißt, nichts von dieser Änderung nicht verloren geht. Die Elementvorlagen wurden mit n3657 eingeführt, um die Verwendung heterogener Schlüssel mit den assoziativen Containern zu ermöglichen. Ich sehe kein konkretes Beispiel, wo dies nützlich ist, außer dem Beispiel, das gut und schlecht ist!Die
is_transparent
Verwendung soll unerwünschte Conversions vermeiden. Wenn die Mitgliedsvorlagen nicht eingeschränkt wären, könnte vorhandener Code Objekte direkt passieren, die ohne die Mitgliedsvorlagen konvertiert worden wären. Der Beispielanwendungsfall von n3657 ist das Suchen eines Objekts in einemstd::set<std::string>
Zeichenfolgenliteral: Mit der C ++ 11-Definition wird einstd::string
Objekt erstellt, wenn Zeichenfolgenliterale an die entsprechende Elementfunktion übergeben werden. Mit der Änderung ist es möglich, das String-Literal direkt zu verwenden. Wenn das zugrunde liegende Vergleichsfunktionsobjekt ausschließlich in Bezugstd::string
darauf implementiert wird , ist dies schlecht, da jetztstd::string
für jeden Vergleich ein erstellt wird. Wenn andererseits das zugrunde liegende Vergleichsfunktionsobjekt a annehmen kannstd::string
und ein String-Literal, das die Konstruktion eines temporären Objekts vermeiden kann.Der verschachtelte
is_transparent
Typ im Vergleichsfunktionsobjekt bietet eine Möglichkeit, anzugeben, ob die Vorlagenelementfunktion verwendet werden soll: Wenn das Vergleichsfunktionsobjekt heterogene Argumente verarbeiten kann, definiert es diesen Typ, um anzuzeigen, dass es effizient mit verschiedenen Argumenten umgehen kann. Beispielsweise delegieren die neuen Operatorfunktionsobjekte nur anoperator<()
und behaupten, transparent zu sein. Zumindest funktioniert das, fürstd::string
das weniger überlastet wurde als für diechar const*
als Argument genommenen Operatoren . Da diese Funktionsobjekte auch neu sind, selbst wenn sie das Falsche tun (dh für einen Typ eine Konvertierung erfordern), wäre dies zumindest keine stille Änderung, die zu einer Leistungsverschlechterung führt.quelle
is_transparent
es im Vergleichsfunktionsobjekt gemäß 23.2.4 [assoziativ.erfordernisse] Absatz 13 definiert ist. Die Standardvergleichsfunktionsobjekte sindstd::less<Key>
gemäß 23.4.2 [assoziativ.map.syn] und 23.4. 3 [assoziative.set.syn]. Nach 20.10.5 [Vergleich] Absatz 4 die allgemeine Vorlage fürstd::less<...>
sich nicht definieren eine verschachtelte Art ,is_transparent
aber diestd::less<void>
Spezialisierung der Fall ist. Das heißt, nein, Sie erhalten standardmäßig keinen transparenten Operator.is_transparent
?Das Folgende sind alle Copy-Pasta von n3657 .
Um Yakk zu zitieren ,
und n3657,
n3421 bietet ein Beispiel für "Transparent Operator Functors" .
Der vollständige Code ist hier .
quelle
std::set<std::string>
profitieren tatsächlich von „Passieren derchar const *
durch“, oder müssen Sie machenstd::set<std::string, std::less<>>
?With the change proposed by N3465 the std::set::find() function would be an unconstrained template which would pass the const char* through to the comparator function, std::less<std::string>, which would construct a std::string temporary for every comparison. The LWG considered this performance problem to be a serious issue.
Stephan T Lavavej spricht über Probleme, bei denen der Compiler ständig Provisorien erstellt, und wie sein Vorschlag für transparente Operator-Funktoren dies in c ++ 1y lösen wird
GoingNative 2013 - Helfen Sie dem Compiler nicht (ungefähr zur vollen Stunde)
quelle