Tôi đang gặp rắc rối hiểu tại sao các nhà xây dựng Foo
di chuyển cố gắng gọi ~ptr
trong ví dụ sau:Trường hợp nào destructor ẩn trong mã này?
#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.
Điều gì đang xảy ra? Tôi đang viết các nhà thầu di chuyển để tránh chạy các bản sao ctors và dtors. Lưu ý rằng đây là tệp tiêu đề cố gắng ẩn triển khai của nó (thành ngữ pimpl), do đó, việc tạo FooDeleter
một loại đầy đủ không phải là một tùy chọn.
EDIT: Sau câu trả lời của Bo, tôi đã thêm noexcept
ở mọi nơi tôi có thể (chỉnh sửa ở trên). Nhưng các lỗi vẫn như cũ.
nhìn chằm chằm vào mã đó trong một giây và nhận được một cơn sốt nhỏ ngay lập tức, cảm ơn câu hỏi, tôi có một vấn đề tương tự gần đây may mắn không theo đuổi – lurscher
Không phải là câu trả lời cho câu hỏi của bạn. Deleter (m_t); 'không có nghĩa là bạn nghĩ nó có nghĩa là gì. Nó định nghĩa một biến được sử dụng không được sử dụng dư thừa 'm_t' của kiểu' Deleter'. – hvd
"Tôi đang viết các nhà thầu di chuyển để tránh chạy các bản sao ctors và dtors." Đó không phải là một lý do chính đáng để viết một hàm tạo di chuyển. Lý do để viết các nhà xây dựng di chuyển là vì nó là một loại container cấp thấp cần di chuyển ngữ nghĩa, hoặc bạn đang sử dụng Visual Studio mà không ngầm tạo ra các hàm tạo di chuyển cho bạn. Nếu không, hãy để trình biên dịch thực hiện công việc của nó. –