В следующем коде объявлен объект wrapper<T>
, который содержит movable<T>
, где T
является неполным типом. Деструктор movable
создается таким образом, что он не может быть создан без полного знания T
, но деструктор wrapper
только вперед-декларирован, что означает, что его должно быть достаточно, если ~movable()
создается в точке определение ~wrapper()
.
#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
в примере кода.)
В чем причина такого поведения, и есть ли способ обойти его?