Я пишу C++ / обертка ООП для Lua. Мой код:
class LuaState
{
boost::shared_ptr L;
LuaState(): L( luaL_newstate(), LuaState::CustomDeleter )
{
}
}
Проблемой является lua_State, неполный тип, и shared_ptr конструктор требует полного типа. И мне нужно безопасное совместное использование указателя. (Забавная вещь, в документах повышения говорится, что большинство функций не требует полного типа, но конструктора, требует, таким образом, нет никакого способа использовать его. http://www.boost.org/doc/libs/1_42_0/libs/smart_ptr/smart_ptr.htm)
Банка я могу решить это?Спасибо.
Вы используете свой собственный удалитель, а это означает, что вам не обязательно иметь полный тип при построении. Единственное требование - чтобы CustomDeleter
мог это обработать. (он может преобразовать переданный указатель в полный тип, например (например, из void *
в CompleteType *
).
Предпосылкой полноты является то, что когда-то конструктор shared_ptr
вызывается с помощью средства удаления по умолчанию, он создает экземпляр класса, который содержит строку delete p;
- и для того, чтобы этот код был правильным, p
не должен быть неполным. Деструктор вызовет этот код удаления косвенно, поэтому он не зависит от полноты типа.
Однако, если вы передадите свой собственный удалитель, требования вашего собственного удалителя будут применяться. Обязательно определите CustomDeleter
после завершения lua_State
.
Учитывая, что lua_State * не может быть клонирован, имеет ли смысл копирование объекта LuaState? Какова ожидаемая семантика копирования такого изначально некопируемого объекта?
Похоже, вам нужно поверхностное копирование - и лучший способ сделать это - сделать LuaState не копируемым и управлять временем жизни lua_State, тогда вы можете передать состояние как shared_ptr
.
Казалось странным, что boost :: shared_ptr
требовал полного типа для создания экземпляра, поэтому я написал этот небольшой тест, демонстрирующий обратное (код в конце).
Я считаю, что проблема не в том, что тип должен быть полным, а во втором аргументе, который вы передаете конструктору shared_ptr
, который выглядит как функция-член. Второй аргумент должен быть чем-то вызываемым с одним аргументом-указателем. Если вы хотите использовать функцию-член вашей оболочки, вы можете использовать boost :: bind
для адаптации интерфейса.
Может быть, вы имели в виду?:
LuaState(): L( luaL_newstate(), boost::bind(LuaState::CustomDeleter,this,_1) )
{
}
Демонстрация того, что boost :: shared_ptr
не требует полных типов:
// 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;
}