次のコードではmovable<T>
を含むwrapper<T>
オブジェクトが宣言されています。ここでT
は不完全な型です。 movable
のデストラクタは、T
の完全な知識なしにはインスタンス化できないように作られていますが、wrapper
のデストラクタは前方宣言されているだけです。つまり~wrapper()
の定義ポイントで~movable()
がインスタンス化されていれば十分です。noexceptコンストラクタはデストラクタのインスタンス化を必要とするのはなぜですか?
#include <utility>
template<class T>
struct movable {
movable() noexcept = default;
~movable() noexcept { (void) sizeof(T); }
movable(const movable&) noexcept = delete;
movable(movable &&) noexcept = default;
};
template<class T>
class wrapper {
public:
movable<T> m;
wrapper() noexcept = default;
wrapper(wrapper &&) noexcept = default;
~wrapper();
};
struct incomplete;
int main() {
/* extern */ wrapper<incomplete> original;
wrapper<incomplete> copy(std::move(original));
}
しかし、wrapper()
は~movable()
をインスタンス化したいと考えています。例外の場合には、メンバーの破壊が可能でなければならないが、movable()
とwrapper()
はどちらも例外ではない。興味深いことに、移動コンストラクタは正常に動作します(例コードのextern
部分のコメントを外してみてください)。
この動作の理由は何ですか?回避する方法はありますか?
打ち鳴らすコンパイルが失敗します。 – interjay
Hm、 "クラステンプレートの完全性がプログラムのセマンティクスに影響を与える可能性がある場合、クラステンプレートはインスタンス化されます" ...多分それは何か関係がありますか? –
クラスに複数のメンバがあり、構築中に初期化のうちの1つがスローされた場合、前に完了した初期化は、それぞれのメンバのデストラクタを呼び出すことによって元に戻す必要があります。私はあなたが見るものはこれに関連していると思います。 – dyp