2017-09-05 3 views
3

Wenn ich einen Typ habe, der std::is_nothrow_move_constructible ist, und ich muss es in einem std::any oder std::variant speichern, welchen würden Sie empfehlen zu verwenden und warum? Welcher wird den geringsten Overhead geben? Edit: Was sind die verschiedenen Anwendungsfälle für std::variant vs std::any?STD :: Variante vs STD :: any, wenn der Typ ist bewegbar construcible

class MyType 
{ 
public: 
    MyType(const MyType&) = default; 
    MyType(MyType&&) = default; 
    MyType() = default; 
}; 

int main(int argc, char* argv[]) 
{ 
    static_assert(std::is_nothrow_move_constructible<MyType>::value, "Not move constructible"); 
    return 0; 
} 
+9

Sie werden für verschiedene Zwecke verwendet. –

+0

@RinatVeliakhmedov Hätten Sie etwas dagegen zu erarbeiten. Ich bin mir nicht sicher über die verschiedenen Anwendungsfälle. – 0xBADF00

+3

Verwenden Sie std :: Variante, wenn Sie die Typen kennen, die gespeichert werden können (im Grunde eine sichere Union), std :: any, wenn Sie nicht tun. – ralismark

Antwort

5

Wenn Sie die Typen kennen, verwenden Sie std::variant. In diesem Fall kennen Sie alle möglichen Typen und verwenden std::variant::visit(), um den Besucher auf die Varianten anzuwenden.

Wenn nicht, verwenden Sie std::any. Sie können darüber nachdenken, wenn Sie mit generischen Typen arbeiten. Mit anderen Worten, wenn die Typen nicht a priori bekannt sind.


denen man die am wenigsten Overhead geben?

std::variant, kann den Heap nicht verwenden. Es ist nicht erlaubt. Es gibt keine Möglichkeit, tatsächlich eine Struktur zu haben, die eine mögliche Variante von sich selbst ohne eine dynamische Zuweisung enthält, da eine solche Struktur leicht in der Größe gezeigt werden kann, wenn sie statisch deklariert wird. Source.

Im Gegensatz dazu kann std::any dies tun. Als Ergebnis wird der erste schnellere Konstruktions- und Kopiervorgänge haben.

+0

Ich bin neugierig, wie verwenden Sie ein 'void *' oder besser gesagt 'std :: any', wenn Sie nicht einmal seine möglichen Typen kennen? –

+0

@PasserBy überprüfen Sie dies [Beispiel] (https://Stackoverflow.com/documentation/c%2b%2b/7894/stdany#t=201709051128521966086). Aber ich verstehe deinen Standpunkt. Vielleicht verwirrt dieser Teil meiner Antwort den Leser und sollte entfernt werden. Was denken Sie? – gsamaras

+0

Sieht man sich das Beispiel IMO an, so wäre der zwingende Grund, 'std :: any' zu verwenden, genau, weil es eine bestimmte Menge an Speicher verwendet, da der Typ (scheinbar) letztendlich doch bekannt ist. –

2

std::any reserviert den Speicher für den Wert aus dem Heap. Während std::variant den Heap nicht verwendet, ist es effizienter in Bezug auf Aufbau und Kopie und mehr Cache-freundlich, da der Wert direkt im Objekt gespeichert wird und es keine Umleitung und virtuelle Funktionen für den Zugriff darauf gibt. Die Schnittstelle std::variant ist reicher und einfacher zu verwenden.

std::any ist nur nützlich, wenn std::variant aus irgendeinem Grund nicht verwendet werden kann.

+0

Check [this] (https://stackoverflow.com/a/45419725/4832499) einfache Implementierung von 'std :: variant'. Soweit ich sehen kann, gibt es keinen Weg um eine Nachschlagetabelle/einen virtuellen Funktionsaufruf für "std :: visit" zu finden, und auf die eine oder andere Weise wird es eine Indirektion geben. TLDR-Cache-Freundlichkeit klingt nicht richtig –

+0

@PasserBy Ihre Aussage ist falsch, Visitation erfordert keine virtuellen Funktionen. –

+0

Können Sie ein Beispiel geben, wie man 'std :: visit' ohne irgendeine Form von Indirektion implementiert? Ich kenne wirklich keinen Weg –

2

Aus Gründen der Typsicherheit, lose Kopplung und einfache Wartung:

bevorzugen variant über any wenn Sie können.

Weil im Wesentlichen std::any ist Zucker-Beschichtung um eine klonbare std::unique_ptr<void, some_deleter>.

Das hat ein wenig Schutz um schlechte Casts (es wird eher werfen als crashen, was in vielen Programmen dasselbe ist).

Verwandte Themen