Um das zu verstehen enum
, betrachten Sie zunächst den Destruktor ohne ihn:
~scoped_ptr() {
delete ptr_;
}
wo ptr_
ist ein C*
. Wenn der Typ C
zu diesem Zeitpunkt unvollständig ist, dh der Compiler nur weiß struct C;
, dass (1) für die C-Instanz, auf die verwiesen wird , ein standardmäßig generierter Nichtstun-Destruktor verwendet wird. Es ist unwahrscheinlich, dass dies für ein Objekt, das von einem intelligenten Zeiger verwaltet wird, richtig ist.
Wenn das Löschen über einen Zeiger auf einen unvollständigen Typ immer ein undefiniertes Verhalten hatte, könnte der Standard nur verlangen, dass der Compiler es diagnostiziert und fehlschlägt. Aber es ist genau definiert, wenn der eigentliche Destruktor trivial ist: Wissen, das der Programmierer haben kann, der Compiler jedoch nicht. Warum die Sprache dies definiert und zulässt, ist mir ein Rätsel, aber C ++ unterstützt viele Praktiken, die heute nicht als Best Practices angesehen werden.
Ein vollständiger Typ hat eine bekannte Größe und wird daher sizeof(C)
genau dann kompiliert, wenn C
es sich um einen vollständigen Typ handelt - mit bekanntem Destruktor. So kann es als Wache verwendet werden. Ein Weg wäre einfach
(void) sizeof(C); // Type must be complete
Ich würde vermuten, dass der Compiler mit einigen Compilern und Optionen diese optimiert, bevor er feststellen kann, dass sie nicht kompiliert werden sollten und dass dies enum
ein Weg ist, um ein solches nicht konformes Compilerverhalten zu vermeiden:
enum { type_must_be_complete = sizeof(C) };
Eine alternative Erklärung für die Wahl enum
eines Ausdrucks und nicht nur eines verworfenen Ausdrucks ist einfach die persönliche Präferenz.
Oder wie James T. Hugget in einem Kommentar zu dieser Antwort vorschlägt : „Die Aufzählung kann eine Möglichkeit sein, beim Kompilieren eine pseudo-portable Fehlermeldung zu erstellen.“
(1) Der standardmäßig generierte Do-Nothing-Destruktor für einen unvollständigen Typ war ein Problem mit old std::auto_ptr
. Es war so heimtückisch, dass es seinen Weg in einen GOTW-Artikel über die PIMPL-Sprache fand , der vom Vorsitzenden des internationalen C ++ - Standardisierungskomitees Herb Sutter verfasst wurde. Natürlich wird man heutzutage, da dies std::auto_ptr
veraltet ist, stattdessen einen anderen Mechanismus verwenden.
ptr_
imsizeof
as alssizeof(*ptr_)
verwendensizeof(C)
.