这段代码中的析构函数隐藏在哪里?

发布于 2025-01-08 02:47:22 字数 2403 浏览 0 评论 0原文

我无法理解为什么 Foo 移动构造函数尝试在以下示例中调用 ~ptr

#include <utility>

template <typename T, typename Policy>
class ptr {
    T * m_t;
public:
    ptr() noexcept : m_t(0) {}
    explicit ptr(T *t) noexcept : m_t(t) {}
    ptr(const ptr &other) noexcept : m_t(Policy::clone(other.m_t)) {}
    ptr(ptr &&other) noexcept : m_t(other.m_t) { other.m_t = 0; }
    ~ptr() noexcept { Policy::delete_(m_t); }
    ptr &operator=(const ptr &other) noexcept
    { ptr copy(other); swap(copy); return *this; }
    ptr &operator=(ptr &&other) noexcept
    { std::swap(m_t,other.m_t); return *this; }

    void swap(ptr &other) noexcept { std::swap(m_t, other.m_t); }

    const T * get() const noexcept { return m_t; }
    T * get() noexcept { return m_t; }
};

class FooPolicy;
class FooPrivate;
class Foo {
    // some form of pImpl:
    typedef ptr<FooPrivate,FooPolicy> DataPtr;
    DataPtr d;
public:
    // copy semantics: out-of-line
    Foo();
    Foo(const Foo &other);
    Foo &operator=(const Foo &other);
    ~Foo();

    // move semantics: inlined
    Foo(Foo &&other) noexcept
      : d(std::move(other.d)) {} // l.35 ERR: using FooDeleter in ~ptr required from here
    Foo &operator=(Foo &&other) noexcept
    { d.swap(other.d); return *this; }
};

GCC 4.7:

foo.h: In instantiation of ‘ptr<T, Policy>::~ptr() [with T = FooPrivate; Policy = FooPolicy]’:
foo.h:34:44:   required from here
foo.h:11:14: error: incomplete type ‘FooPolicy’ used in nested name specifier

Clang 3.1-pre:

foo.h:11:14: error: incomplete type 'FooPolicy' named in nested name specifier
    ~ptr() { Policy::delete_(m_t); }
             ^~~~~~~~
foo.h:34:5: note: in instantiation of member function 'ptr<FooPrivate, FooPolicy>::~ptr' requested here
    Foo(Foo &&other) : d(std::move(other.d)) {}
    ^
foo.h:23:7: note: forward declaration of 'FooPolicy'
class FooPolicy;
      ^
foo.h:11:20: error: incomplete definition of type 'FooPolicy'
    ~ptr() { Policy::delete_(m_t); }
             ~~~~~~^~
2 errors generated.

发生了什么事?我正在编写移动构造函数以避免运行复制者和数据复制者。请注意,这是一个试图隐藏其实现的头文件(pimpl idiom),因此不能选择将 FooDeleter 设为完整类型。

编辑:在 Bo 回答之后,我在所有可能的地方添加了 noexcept (在上面编辑过)。但错误仍然是一样的。

I'm having trouble understanding why the Foo move constructor tries to invoke ~ptr in the following example:

#include <utility>

template <typename T, typename Policy>
class ptr {
    T * m_t;
public:
    ptr() noexcept : m_t(0) {}
    explicit ptr(T *t) noexcept : m_t(t) {}
    ptr(const ptr &other) noexcept : m_t(Policy::clone(other.m_t)) {}
    ptr(ptr &&other) noexcept : m_t(other.m_t) { other.m_t = 0; }
    ~ptr() noexcept { Policy::delete_(m_t); }
    ptr &operator=(const ptr &other) noexcept
    { ptr copy(other); swap(copy); return *this; }
    ptr &operator=(ptr &&other) noexcept
    { std::swap(m_t,other.m_t); return *this; }

    void swap(ptr &other) noexcept { std::swap(m_t, other.m_t); }

    const T * get() const noexcept { return m_t; }
    T * get() noexcept { return m_t; }
};

class FooPolicy;
class FooPrivate;
class Foo {
    // some form of pImpl:
    typedef ptr<FooPrivate,FooPolicy> DataPtr;
    DataPtr d;
public:
    // copy semantics: out-of-line
    Foo();
    Foo(const Foo &other);
    Foo &operator=(const Foo &other);
    ~Foo();

    // move semantics: inlined
    Foo(Foo &&other) noexcept
      : d(std::move(other.d)) {} // l.35 ERR: using FooDeleter in ~ptr required from here
    Foo &operator=(Foo &&other) noexcept
    { d.swap(other.d); return *this; }
};

GCC 4.7:

foo.h: In instantiation of ‘ptr<T, Policy>::~ptr() [with T = FooPrivate; Policy = FooPolicy]’:
foo.h:34:44:   required from here
foo.h:11:14: error: incomplete type ‘FooPolicy’ used in nested name specifier

Clang 3.1-pre:

foo.h:11:14: error: incomplete type 'FooPolicy' named in nested name specifier
    ~ptr() { Policy::delete_(m_t); }
             ^~~~~~~~
foo.h:34:5: note: in instantiation of member function 'ptr<FooPrivate, FooPolicy>::~ptr' requested here
    Foo(Foo &&other) : d(std::move(other.d)) {}
    ^
foo.h:23:7: note: forward declaration of 'FooPolicy'
class FooPolicy;
      ^
foo.h:11:20: error: incomplete definition of type 'FooPolicy'
    ~ptr() { Policy::delete_(m_t); }
             ~~~~~~^~
2 errors generated.

What's going on? I'm writing move constructors to avoid running copy ctors and dtors. Note that this is a header file that tries to hide its implementation (pimpl idiom), so making FooDeleter a full type isn't an option.

EDIT: After Bo's answer, I added noexcept everywhere I could (edited in above). But the errors are still the same.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

給妳壹絲溫柔 2025-01-15 02:47:22

您创建一个新的 Foo 对象,其中包含一个 ptr 成员。如果 Foo 构造函数失败,编译器必须为部分构造的 Foo 的任何完全构造的成员调用析构函数。

但它无法实例化 ~ptr(),因此失败。

私有析构函数也有类似的情况。这也会阻止您创建该类型的对象(除非由友元或成员函数完成)。

You create a new Foo object that contains a ptr<something> member. In case the Foo constructor fails, the compiler has to call the destructors for any completely constructed members of the partially constructed Foo.

But it cannot instantiate ~ptr<incomplete_type>(), so that fails.

You have a similar case with a private destructor. That also stops you from creating objects of that type (unless done from a friend or a member function).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文