Ich möchte eine std::set
mit einer benutzerdefinierten Vergleichsfunktion erstellen . Ich könnte es als Klasse mit definieren operator()
, aber ich wollte die Möglichkeit genießen, ein Lambda dort zu definieren, wo es verwendet wird. Deshalb habe ich beschlossen, die Lambda-Funktion in der Initialisierungsliste des Konstruktors der Klasse zu definieren, die das std::set
als Mitglied hat. Aber ich kann den Typ des Lambda nicht bekommen. Bevor ich fortfahre, hier ein Beispiel:
class Foo
{
private:
std::set<int, /*???*/> numbers;
public:
Foo () : numbers ([](int x, int y)
{
return x < y;
})
{
}
};
Nach der Suche habe ich zwei Lösungen gefunden: eine mit std::function
. Lassen Sie einfach den eingestellten Vergleichsfunktionstyp sein std::function<bool (int, int)>
und übergeben Sie das Lambda genau wie ich. Die zweite Lösung besteht darin, eine make_set-Funktion wie zu schreiben std::make_pair
.
LÖSUNG 1:
class Foo
{
private:
std::set<int, std::function<bool (int, int)> numbers;
public:
Foo () : numbers ([](int x, int y)
{
return x < y;
})
{
}
};
LÖSUNG 2:
template <class Key, class Compare>
std::set<Key, Compare> make_set (Compare compare)
{
return std::set<Key, Compare> (compare);
}
Die Frage ist, habe ich einen guten Grund, eine Lösung der anderen vorzuziehen? Ich bevorzuge die erste, weil sie Standardfunktionen verwendet (make_set ist keine Standardfunktion), aber ich frage mich: Macht die Verwendung std::function
den Code (möglicherweise) langsamer? Ich meine, verringert es die Wahrscheinlichkeit, dass der Compiler die Vergleichsfunktion einbindet, oder sollte es klug genug sein, sich genau so zu verhalten, als wäre es ein Lambda-Funktionstyp und nicht std::function
(ich weiß, in diesem Fall kann es keine sein Lambda-Typ, aber weißt du, ich frage im Allgemeinen)?
(Ich benutze GCC, möchte aber wissen, was beliebte Compiler im Allgemeinen tun.)
ZUSAMMENFASSUNG, NACHDEM ICH VIELE GROSSE ANTWORTEN ERHALTEN HABE:
Wenn die Geschwindigkeit kritisch ist, ist die beste Lösung, eine Klasse mit operator()
aka functor zu verwenden. Für den Compiler ist es am einfachsten, Indirektionen zu optimieren und zu vermeiden.
Verwenden Sie für eine einfache Wartung und eine bessere Allzwecklösung mit C ++ 11-Funktionen std::function
. Es ist immer noch schnell (nur ein bisschen langsamer als der Funktor, aber es kann vernachlässigbar sein) und Sie können jede Funktion verwenden - std::function
, Lambda, jedes aufrufbare Objekt.
Es gibt auch eine Option zur Verwendung eines Funktionszeigers, aber wenn es kein Geschwindigkeitsproblem gibt, ist es meiner Meinung std::function
nach besser (wenn Sie C ++ 11 verwenden).
Es gibt eine Option, um die Lambda-Funktion an einer anderen Stelle zu definieren, aber dann erhalten Sie nichts davon, wenn die Vergleichsfunktion ein Lambda-Ausdruck ist, da Sie sie genauso gut zu einer Klasse machen könnten operator()
und der Ort der Definition ohnehin nicht die Mengenkonstruktion wäre.
Es gibt weitere Ideen, z. B. die Verwendung der Delegierung. Wenn Sie eine gründlichere Erklärung aller Lösungen wünschen, lesen Sie die Antworten :)