を理解するにはenum
、それなしでデストラクタを検討することから始めます。
~scoped_ptr() {
delete ptr_;
}
はどこptr_
ですC*
。タイプがいる場合C
、この時点で不完全である、すなわち、すべてのコンパイラが知っているとされstruct C;
、その後、(1)デフォルトで生成され、何も行わないデストラクタは、Cのインスタンスのために使用されていると指摘しました。これは、スマートポインタによって管理されるオブジェクトに対して行うべき正しいことではない可能性があります。
不完全な型へのポインタを介した削除で常に未定義の動作があった場合、標準ではコンパイラに診断を要求して失敗する可能性があります。しかし、実際のデストラクタが些細なものである場合、それは明確に定義されています。プログラマーは持つことができるが、コンパイラーは持つことができない知識です。言語がこれを定義して許可する理由は私にはわかりませんが、C ++は、今日ではベストプラクティスとは見なされていない多くのプラクティスをサポートしています。
完全な型のサイズは既知であるため、sizeof(C)
がC
完全な型である場合にのみ、既知のデストラクタを使用してコンパイルされます。そのため、ガードとして使用できます。1つの方法は単純です
(void) sizeof(C);
いくつかのコンパイラーとオプションを使用すると、コンパイラーは、コンパイルすべきではないことに気付く前にそれを最適化し、そのような不適合なコンパイラーの動作を回避する方法であると推測しますenum
。
enum { type_must_be_complete = sizeof(C) };
enum
単に破棄された表現ではなく、選択するための代替の説明は、単に個人的な好みです。
または、James T. Huggetがこの回答へのコメントで示唆しているように、「列挙型は、コンパイル時に疑似ポータブルエラーメッセージを作成する方法である可能性があります」。
(1)不完全な型に対してデフォルトで生成された何もしないデストラクタは、oldの問題でしたstd::auto_ptr
。それは非常に陰湿だったので、国際的なC ++標準化委員会のハーブサッターの委員長によって書かれたPIMPLイディオムに関するGOTWアイテムになりました。もちろん、現在std::auto_ptr
は非推奨ですが、代わりに他のメカニズムを使用します。
ptr_
はsizeof
、のsizeof(*ptr_)
代わりにasで自分自身を使用したいと思いsizeof(C)
ます。