2015-12-03 9 views
5

Ist es permitable std::optional (derzeit std::experimental::optional) so zu gestalten, dass für trivialen Standard konstruierbar Typen Tstd::optional<T> entsprechend ist auch trivialer Standard konstruierbar?trivialen Standard konstruierbar std :: optional und std :: Variante

Die gleiche Frage eingehend std::variant und seine Integraldiskriminator.

Meine eigene Antwort ist: "Nein, es kann nicht auf diese Weise entworfen werden, weil der Wert seines Integraldiskriminators, der während der Standardinitialisierung erhalten wird, unbestimmt ist, wenn das Objekt eine automatische Speicherdauer hat oder reinterpret_cast. Null initialisierter Speicher. " Die Anforderung an den Benutzer, jedes Mal eine Wert-Initialisierung durchzuführen, ist für mich nicht erlaubt.

+0

Kann ich Sie im Austausch fragen, warum es Ihnen wichtig ist? Ich kann mir vorstellen, warum du optional trivial kopierbar sein solltest. Aber warum trivial-default-konstruierbar? Was kauft es dir? – Andrzej

+0

@Andrzej Der Container (wie 'optional' oder' variant') sollte so generisch wie möglich sein, oder? Ich versuche, ["Variante" für conexpr] zu entwerfen (http://codereview.stackexchange.com/questions/112218/trivial-full-fledged-variant-for-constexpr-proof-of-concept). Und derzeit hat es über die Fähigkeit. Aber ich denke "vielleicht sollte ich es leugnen?". – Orient

+0

@Andrzej Irgendwann habe ich in meiner 'Variante' einen" Bug "gefunden. Standard initialisierte Objekte haben ein unterschiedliches Verhalten in der Kompilierzeit (conexpr) und der Laufzeit. Dann lese ich über [Intiialisierungen] (http://en.cppreference.com/w/cpp/language/initialization). Und fand heraus, dass es UB gibt, meine voreingestellte iniialisierte "Variante" auf dem Stapel zu verwenden. – Orient

Antwort

8

Ihre Antwort ist richtig: Sie können nicht. Die Spezifikation erfordert, dass ihr "initialisiertes Flag" bei der Standardkonfiguration auf false gesetzt wird.

3

Wie Sie selbst erklärt haben, können Sie std :: optional nicht so implementieren, weil Sie seine Semantik ändern würden (is_trivial_default_constructible ist Teil der Klassenschnittstelle).

Wenn Sie diese Semantik jedoch aus irgendeinem Grund in Ihrem Code benötigen, gibt es keinen Grund, warum Sie keine sehr ähnliche optionale Klasse implementieren können, die trivial standardmäßig konstruierbar ist. Dann, wenn verwendet, nur Null initialisieren Sie es über {} und - wenn das ist, was Sie wollen - behandeln Sie Null als wahr im Bool-Operator.