在以下代码中,声明了一个包含一个可移动对象
movable<T>
的wrapper<T>
对象,其中T
是不完整类型。 movable
的析构函数被设计成不能在没有完整了解T
的情况下实例化,但是wrapper
的析构函数只是前向声明,这意味着在定义~wrapper()
时实例化~movable()
应该是足够的。请注意保留HTML标签。#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()
都是 noexcept 的。有趣的是,移动构造函数可以正常工作(请尝试取消注释示例代码中的 extern
部分)。
这种行为的原因是什么,有没有办法规避它?
extern
,clang编译仍然失败。 - interjaymovable
的非平凡析构函数会影响默认构造函数的平凡性,但不会影响移动构造函数的平凡性(出人意料)。 - dyp