Чтобы понять это enum
, начните с рассмотрения деструктора без него:
~scoped_ptr() {
delete ptr_;
}
где ptr_
а C*
. Если тип C
на этом этапе является неполным, то есть все, что известно компилятору struct C;
, то (1) для указанного экземпляра C используется деструктор, созданный по умолчанию . Вряд ли это будет правильным решением для объекта, управляемого интеллектуальным указателем.
Если удаление с помощью указателя на неполный тип всегда имело неопределенное поведение, тогда стандарт мог бы просто потребовать, чтобы компилятор диагностировал его и завершился ошибкой. Но это четко определено, когда реальный деструктор тривиален: знания, которые может иметь программист, но нет у компилятора. Я не понимаю, почему язык определяет и допускает это, но C ++ поддерживает многие практики, которые сегодня не считаются лучшими.
Полный тип имеет известный размер и, следовательно, sizeof(C)
будет компилироваться тогда и только тогда, когда C
это полный тип - с известным деструктором. Так что его можно использовать как охранник. Один путь был бы просто
(void) sizeof(C);
Я предполагаю, что с некоторым компилятором и параметрами компилятор оптимизирует его, прежде чем он сможет заметить, что он не должен компилироваться, и что enum
это способ избежать такого несоответствующего поведения компилятора:
enum { type_must_be_complete = sizeof(C) };
Альтернативное объяснение выбора, enum
а не просто отброшенное выражение, - это просто личные предпочтения.
Или, как предлагает Джеймс Т. Хаггет в комментарии к этому ответу, «перечисление может быть способом создания псевдопереносимого сообщения об ошибке во время компиляции».
(1) Сгенерированный по умолчанию деструктор бездействия для неполного типа был проблемой со старым std::auto_ptr
. Он был настолько коварен, что попал в статью GOTW об идиоме PIMPL , написанную председателем международного комитета по стандартизации C ++ Хербом Саттером. Конечно, в настоящее время это std::auto_ptr
не рекомендуется, вместо этого можно использовать какой-то другой механизм.
ptr_
себя вsizeof
assizeof(*ptr_)
вместоsizeof(C)
.