Diese Frage , die heute Morgen gestellt wurde, hat mich gefragt, welche Funktionen Ihrer Meinung nach in der C ++ - Standardbibliothek fehlen und wie Sie die Lücken mit Wrapper-Funktionen gefüllt haben. Zum Beispiel hat meine eigene Dienstprogrammbibliothek diese Funktion zum Vektoranhängen:
template <class T>
std::vector<T> & operator += ( std::vector<T> & v1,
const std::vector <T> & v2 ) {
v1.insert( v1.end(), v2.begin(), v2.end() );
return v1;
}
und dieses zum Löschen (mehr oder weniger) jedes Typs - besonders nützlich für Dinge wie std :: stack:
template <class C>
void Clear( C & c ) {
c = C();
}
Ich habe noch ein paar mehr, aber ich bin daran interessiert, welche Sie verwenden? Bitte beschränken Sie die Antworten auf Wrapper- Funktionen, dh nicht mehr als ein paar Codezeilen.
c.swap(C())
, um einen Container zu löschen?Antworten:
boost :: array
enthält (container, val) (ganz einfach, aber bequem).
remove_unstable (Anfang, Ende, Wert)
Eine schnellere Version von std :: remove mit der Ausnahme, dass die Reihenfolge der verbleibenden Objekte nicht beibehalten wird.
(Im Fall eines Vektors von Pod-Typen (int, float usw.) und fast allen Objekten, die entfernt werden, ist std :: remove möglicherweise schneller).
quelle
bool sorted=false
) und eine Spezialisierung beisorted==true
anrufenbinary_search
stattfind
?Sehr oft würde ich Vektor als eine Reihe von Elementen in keiner bestimmten Reihenfolge verwenden (und natürlich, wenn ich keine schnellen Überprüfungen dieses Elements in der Menge benötige). In diesen Fällen ist das Aufrufen von erase () Zeitverschwendung, da dadurch die Elemente neu angeordnet werden und mir die Reihenfolge egal ist. Dann ist die O (1) -Funktion nützlich - verschieben Sie einfach das letzte Element an die Position des Elements, das Sie löschen möchten:
quelle
v[index] = st::move(v.back()); v.pop_back();
ist es ungefähr so effizient wie es nur geht.Ok, da dies anscheinend nicht so einfach ist, wie ich dachte, folgt eine Erklärung:
In seinem Konstruktor wird
temp_value
ein Verweis auf eine Variable und eine Kopie des ursprünglichen Werts der Variablen gespeichert. In seinem Destruktor wird die referenzierte Variable auf ihren ursprünglichen Wert zurückgesetzt. Unabhängig davon, was Sie mit der Variablen zwischen Konstruktion und Zerstörung gemacht haben, wird sie zurückgesetzt, wenn dastemp_value
Objekt den Gültigkeitsbereich verlässt.Verwenden Sie es so:
Hier ist ein weiterer Ansatz, der den Scope-Guard-Trick verwendet:
Es ist nur ein bisschen mehr Code für die Kesselplatte, ermöglicht aber eine sauberere Verwendung:
Es entfernt jedoch seine Fähigkeit, in einer Klasse verwendet zu werden.
Hier ist ein dritter Weg, um den gleichen Effekt zu erzielen (der nicht unter den Problemen des potenziellen Werfens von Destruktoren leidet):
Implementierung:
Verwendung:
quelle
Nicht wirklich ein Wrapper, aber der berüchtigte Vermisste
copy_if
. Von hier ausquelle
remove_copy_if()
. : pquelle
T
wirdconst U
und Sie erhalten die beabsichtigte Funktion.const
Deshalbconst
gibt es die Versionen. Da dies möglicherweise ein Fehler dieser bestimmten GCC-Version war, werde ich sie entfernen.:)
:)
&
. Das&
ist da, um den Typabzug der Länge des Arrays zu ermöglichen.Manchmal fühle ich mich wie in der ich bin
begin()
undend()
Hölle. Ich hätte gerne einige Funktionen wie:und andere ähnliche für
std::find
,std::for_each
und im Grunde alle STL-Algorithmen.Ich denke, das
sort(x)
ist viel schneller zu lesen / verstehen alssort(x.begin(), x.end())
.quelle
Ich benutze dieses nicht mehr annähernd so oft, aber es war früher ein Grundnahrungsmittel:
Wird mit mehr aktualisiert, wenn ich mich an sie erinnere. : P.
quelle
boost::lexical_cast<t, t>
.char*
oder a zu nennenstd::string
. Vielleicht ist eine Vorlagenspezialisierung angebracht?boost::lexical_cast
gibt es eine Reihe solcher Spezialisierungen und Fehlerprüfungen. Um die ungerade Zahl zu kennzeichnen, funktioniert dies jedoch einwandfrei.Die Utility-Funktion in jeder Toolbox ist natürlich
copy_if
. Nicht wirklich ein Wrapper.Ein anderer Helfer, den ich normalerweise benutze, ist
deleter
ein Funktor, mit dem ichstd::for_each
alle Zeiger in einem Container lösche.[Bearbeiten] Durch meine "etw.h" graben fand ich auch
vector<wstring> StringSplit(wstring const&, wchar_t);
quelle
Ich habe einen Header, der Folgendes in den Namespace "util" einfügt:
quelle
split()
Schwalben auftretende Fehler instd::getline()
stumm einen Vektor Rückkehr , die zu kurz ist.size()
Ergebnis überprüfen, bevor Sie Ihre Zeichenfolgen abrufen.stringstream
/getline
-Schleife tatsächlich schief gehen könnte (abgesehen davon, dass die Zeichenfolge einfach nicht genug Token hat) . Ich habe hier eine Frage dazu gestellt: stackoverflow.com/questions/2562906/…Der infamös fehlende
erase
Algorithmus:quelle
std::remove
. Zum Beispielstd::unique
.set
.Sprintf einwickeln
Das Ziel ist es, die Formatierung von der Ausgabe zu entkoppeln, ohne Probleme mit sprintf und seiner Art zu bekommen. Es ist nicht schön, aber sehr nützlich, insbesondere wenn Ihre Codierungsrichtlinien iostreams verbieten.
Hier ist eine Version von Neil Butterworth, die nach Bedarf zugewiesen wird. [Revisionsverlauf für Mikes Version anzeigen, die ich als Teilmenge der verbleibenden zwei entfernt habe. Es ähnelt dem von Neil, außer dass letzteres ausnahmesicher ist, indem anstelle von delete [] ein Vektor verwendet wird: Der ctor des Strings löst einen Zuordnungsfehler aus. Mike verwendet auch die später gezeigte Technik, um die Größe im Voraus zu bestimmen. –RP]
Hier ist eine Version von Roger Pate, die die benötigte Größe im Voraus bestimmt . Dies erfordert beschreibbare std :: -Strings, die von gängigen Implementierungen bereitgestellt werden, von C ++ 0x jedoch explizit benötigt werden. [Revisionsverlauf für Marcus 'Version anzeigen, die ich entfernt habe, da sie etwas anders ist, aber im Wesentlichen eine Teilmenge der folgenden. –RP]
Implementierung
Öffentliche Schnittstelle
quelle
man vsnprintf
: "Diese Funktionen geben die Anzahl der gedruckten Zeichen zurück ... oder einen negativen Wert, wenn ein Ausgabefehler auftritt, mit Ausnahme vonsnprintf()
undvsnprintf()
, die die Anzahl der Zeichen zurückgeben, die gedruckt worden wären, wenn die n unbegrenzt wären ... "Daher der Dummy-Aufruf mit einem 0-Puffer, um die benötigte Puffergröße zu messen.boost::spirit
._vscprintf
, bestimmen Sie die erforderliche Größe des Puffers.Das
is_sorted
Dienstprogramm zum Testen von Containern vor dem Anwenden von Algorithmen,include
die einen sortierten Eintrag erwarten:Ja, ich weiß, es wäre besser, das Prädikat zu negieren und die Prädikatversion von
adjacent_find
:) zu verwenden.quelle
assert()
: pAuf jeden Fall boost :: addressof
quelle
quelle
Boost.Bimap
Bibliothek (oderBoost.MultiIndex
für komplexere Situationen)reverse_map
. Betrachten Siemap
hat (1 -> "eins"; 2 -> "eins")reverse_map
erhält ein Element ("eins" -> 1). Die Behauptung wird das fangen. Siehe auch: bijectionEin Blick auf meine
stl_util.h
, viele der Klassiker (deleter Funktionencopy_if
), und auch diese ein (wahrscheinlich auch durchaus üblich, aber ich sehe es in den Antworten bisher nicht gegeben) für die Suche durch eine Karte und Rückkehr entweder den gefundenen Wert oder ein Standard, alaget
in Pythonsdict
:Die Verwendung der Standardeinstellung
null_result
einer Standardkonstruktion entsprichtV
weitgehend dem Verhalten vonstd::map
'soperator[]
, ist jedoch nützlich, wenn die Zuordnung const ist (für mich üblich) oder wenn die Standardkonstruktion V nicht die richtige Verwendung ist.quelle
Hier ist mein Satz von Extra-Utils, die auf einem boost.range'ish std-algo-Wrapper basieren, den Sie möglicherweise für einige Funktionen benötigen. (das ist trivial zu schreiben, das ist das interessante Zeug)
quelle
Ich brauche anscheinend ein kartesisches Produkt, zum Beispiel {A, B}, {1, 2} -> {(A, 1), (A, 2), (B, 1), (B, 2)}
quelle
Ich würde eine solche Append-Funktion beim Namen nennen und Operator + =, Operator * = usw. für elementweise Operationen verwenden, wie zum Beispiel:
einige andere einfache und offensichtliche Wrapper, wie zuvor impliziert:
quelle
vec+=val
würde einen Wert an den Vektor anhängen . (Siehe stackoverflow.com/questions/2551775/. ) Nachdem ich Ihre Implementierung gesehen habe, denke ich, dass dies eine ebenso richtige Interpretation der Bedeutung von+=
ist. Ich würde nicht wissen , was man richtig oder falsch wäre, so dass es wahrscheinlich ist genau so gut , dass wir nicht haben ,+=
fürstd::vector
.operator+()
fehlt ein erstaunlicher früher Einblick in den Standard. Normalerweise erwarte ich überall dort, wo ich den Plus-Operator sehe, eine O (1) -Operation. C ++ macht Dinge, die teuer oder gefährlich sind, ausführlicher oder schwieriger, und ich mag es so. Schauen Sie sich Java an: Einer der schlimmsten Codierungsfehler ist der Missbrauch des Plus-Operators. Andererseits macht C ++ nicht immer billige und schnelle Dinge einfach, aber hey. Gute C ++ - Programmierer sind sehr leistungsbewusst. ;)op+()
dies aufgrund seiner Mehrdeutigkeit überhaupt nicht definiert werden sollte. Vektoren sind jedoch normalerweise Teil eines (mathematischen) Vektorraums, und es gibt eine kanonische Definition für das Hinzufügen von zwei Vektoren und die Skalarmultiplikation. Um Ihr Argument weiter zu führen: Ein einfachesdouble
ist auch ein Vektor. Wenn Sie also zweidouble
Variablen wie hinzufügen,a+b
erwarten Sie eine neuedouble
und keinepair
doppelte(a,b)
. Das Multiplizieren mit einem Skalar ist ebenfalls kanonisch, das Multiplizieren von zwei Vektoren jedoch nicht. Das Überladen sollte also mit Vorsicht erfolgen.Fügen Sie ein neues Element ein und geben Sie es zurück. Dies ist nützlich für einfache Verschiebungssemantiken wie
push_back(c).swap(value)
und verwandte Fälle.Pop und Rückgabe eines Artikels:
quelle
IMO muss es mehr Funktionen geben für
pair
:quelle
PairType
Vorlage nach operator () verschieben? Außerdem sind die doppelten Unterstriche in der Kennung reserviert.unary_function
, was ich irgendwann in meinem Code brauche. Was die doppelten Unterstriche betrifft, danke, dass Sie mich informiert haben - das muss ich ändern.Wenn Sie viele Funktionen verwenden müssen, die Zeiger + Anzahl der Bytes benötigen, ist dies immer gerecht
quelle
Dupliziere einen String mit *:
quelle
Einer meiner Favoriten ist der
Transposer
, der eine Transponierte eines Tupels von Behältern derselben Größe findet. Das heißt, wenn Sie ein habentuple<vector<int>,vector<float>>
, konvertiert es es in einvector<tuple<int, float>>
. Praktisch in der XML-Programmierung. Hier ist, wie ich es gemacht habe.quelle
Ich bin mir nicht sicher, ob diese als Standard-Wrapper qualifiziert sind, aber meine häufig verwendeten Hilfsfunktionen sind:
T und V sind hier Vorlagenargumente. Die letzte Funktion funktioniert genauso wie der [] -Operator, jedoch mit der Automatisierung der Größenänderung, um sie an den erforderlichen Index anzupassen.
quelle
Ähnlich wie bei den zuvor veröffentlichten Beiträgen habe ich eine Vielzahl von Algorithmen zur Vereinfachung der Übergabe von Iteratorargumenten. Ich nenne Algorithmen wie diese:
Ich habe alle Algorithmen so überladen, dass sie
input_sequence_range<>
anstelle der beiden Eingabe-Iteratoren einen einzigen Parameter vom Typ verwenden (Eingabe wie bei allem, was nicht nur Ausgabe ist).Und so
iseq()
funktioniert es:Ebenso habe ich Spezialisierungen für
quelle
Ungeordnetes Löschen für
std::vector
. Der effizienteste Weg, ein Element aus a zu löschen, behältvector
jedoch nicht die Reihenfolge der Elemente bei. Ich habe nicht den Sinn gesehen, es auf andere Container auszudehnen, da die meisten nicht die gleiche Strafe für das Entfernen von Gegenständen aus der Mitte haben. Es ähnelt einigen anderen bereits veröffentlichten Vorlagenstd::swap
, verschiebt jedoch Elemente, anstatt sie zu kopieren.Signum gibt das Vorzeichen eines Typs zurück. Gibt
-1
für negativ,0
für null und1
für positiv zurück.Clamp ist ziemlich selbsterklärend, es klemmt einen Wert so, dass er innerhalb des angegebenen Bereichs liegt. Es verwirrt mich, dass die Standardbibliothek enthält
min
undmax
aber nichtclamp
quelle