2010-03-12 23 views
8

Tôi đang viết một trình bao bọc C++/OOP cho Lua. Mã của tôi là:shared_ptr yêu cầu loại hoàn chỉnh; không thể sử dụng nó với lua_State *

class LuaState 
{ 
    boost::shared_ptr<lua_State> L; 

    LuaState(): L(luaL_newstate(), LuaState::CustomDeleter) 
    { 
    } 
} 

Vấn đề là lua_State là kiểu không đầy đủ và hàm tạo shared_ptr yêu cầu loại hoàn chỉnh. Và tôi cần chia sẻ con trỏ an toàn. (Tài liệu tăng cường vui vẻ nói hầu hết các chức năng không yêu cầu loại hoàn chỉnh, nhưng hàm tạo yêu cầu, vì vậy không có cách nào để sử dụng nó. http://www.boost.org/doc/libs/1_42_0/libs/smart_ptr/smart_ptr.htm)

Tôi có thể giải quyết vấn đề này không? Cảm ơn bạn.

+0

Tại sao bạn cần chia sẻ con trỏ an toàn, nếu tôi có thể yêu cầu. Không thể bạn chỉ cần gọi luaL_newstate trong constructor và lua_close trong destructor. –

+0

LuaState a, b; a = b; // lua_State in b sẽ không bao giờ được phát hành // lua_State trong một bản sẽ được phát hành hai lần Tùy chọn khác là nhân bản cấu trúc lua_State trong hàm tạo bản sao và toán tử =. Nhưng tôi cho rằng đó là giải pháp nặng. –

+0

Bạn không thể sao chép cấu trúc lua_State theo cách thủ công. Nó sẽ nổ tung trên khuôn mặt của bạn. Tôi đã thử nó :) –

Trả lời

4

Bạn đang sử dụng deleter riêng của mình, có nghĩa là bạn không phải có một loại hoàn chỉnh khi xây dựng. Yêu cầu duy nhất là CustomDeleter có thể xử lý điều đó. (Nó có thể chuyển đổi con trỏ truyền đến một loại hoàn chỉnh, ví dụ (nói, từ void* để CompleteType*).

Nền của sự hoàn chỉnh là một khi các nhà xây dựng của shared_ptr được gọi với deleter mặc định, nó sẽ khởi tạo một lớp có chứa các dòng delete p; - và cho mã này là chính xác, p không phải là không đầy đủ.Các destructor sẽ gọi mã deleter này gián tiếp, do đó, nó không phụ thuộc vào tính đầy đủ của các loại.

Tuy nhiên nếu bạn vượt qua Bạn hãy nhớ xác định CustomDeleter sau khi lua_State hoàn thành.

+0

Cảm ơn bạn đã phản hồi. Mã của bạn chính xác là những gì tôi đã viết. Nó không thành công trong "shared_ptr :: checked_delete" khi kiểm tra tĩnh "typedef char type_must_be_complete [sizeof (T)? 1: -1];" –

+0

@topright, nếu bạn sử dụng deleter của riêng bạn mà nó đúng, nó không nên thất bại như thế. Hãy chắc chắn để xác định 'CustomDeleter' của bạn theo cách mà cơ thể của nó xảy ra sau khi định nghĩa' lua_State'. –

+0

Ồ, nó hoạt động ngay bây giờ. Cảm ơn! –

1

Có vẻ lạ rằng boost::shared_ptr sẽ yêu cầu một loại hoàn chỉnh cho việc khởi tạo, vì vậy tôi đã viết bài kiểm tra nhỏ nhỏ này chứng minh ngược lại (mã ở cuối).

Tôi tin rằng vấn đề không phải là với loại cần phải được hoàn thành, nhưng với đối số thứ hai mà bạn đang đi đến constructor shared_ptr, trông giống như một hàm thành viên. Đối số thứ hai phải là một cái gì đó có thể gọi được với một đối số con trỏ duy nhất. Nếu bạn muốn sử dụng chức năng thành viên của trình bao bọc, bạn có thể sử dụng boost::bind để điều chỉnh giao diện.

Có lẽ bạn có nghĩa là ?:

LuaState(): L(luaL_newstate(), boost::bind(LuaState::CustomDeleter,this,_1)) 
{ 
} 

diễn rằng boost::shared_ptr không đòi hỏi các loại hoàn chỉnh:

// forward declarations 
struct test; 
test * create(); 
void destroy(test *); 

// wrapper equivalent to the one in the question 
struct wrapper { 
    boost::shared_ptr<test> sp; 
    wrapper() : sp(create(), destroy) {} 
}; 

// actual definitions 
struct test {}; 
test * create() { return new test; } 
void destroy(test *t) { delete t; } 

// make it executable 
int main() { 
    test t; 
} 
0

Cho rằng một lua_State * không thể được nhân bản vô tính, được sao chép một đối tượng LuaState có ý nghĩa? Ngữ nghĩa dự kiến ​​của việc sao chép như một đối tượng vốn không thể sao chép được là gì?

Các hành vi bạn dường như muốn là cạn sao chép - và cách tốt nhất để làm điều đó là để LuaState là uncopyable và quản lý thời gian tồn tại của lua_State sau đó bạn có thể vượt qua trên toàn tiểu bang như một shared_ptr<LuaState>.

Các vấn đề liên quan