shared_ptr требует полного типа; не может использовать его с lua_State * - PullRequest
8 голосов
/ 12 марта 2010

Я пишу оболочку C ++ / OOP для Lua. Мой код:

class LuaState
{
     boost::shared_ptr<lua_State> 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)

Могу ли я решить эту проблему? Спасибо.

Ответы [ 3 ]

4 голосов
/ 12 марта 2010

Вы используете свой собственный удалитель, что означает, что вам не нужно иметь полный тип при создании. Единственное требование - CustomDeleter может справиться с этим. (например, он может преобразовать переданный указатель в полный тип (скажем, из void* в CompleteType*).

Основа полноты состоит в том, что как только конструктор shared_ptr вызывается с удалителем по умолчанию, он создает экземпляр класса, который содержит строку delete p; - и для правильности этого кода p не должен неполный. Деструктор будет вызывать этот код удаления косвенно, поэтому он не зависит от полноты типа.

Однако, если вы передадите свой собственный удалитель, будут применяться требования вашего собственного удалителя. Обязательно определите CustomDeleter после завершения lua_State.

1 голос
/ 12 марта 2010

Казалось странным, что для 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;
}
0 голосов
/ 12 марта 2010

Учитывая, что lua_State * не может быть клонирован, имеет ли смысл копировать объект LuaState? Какова ожидаемая семантика копирования такого неотъемлемо копируемого объекта?

Поведение, которое вам нужно, это поверхностное копирование - и лучший способ сделать это, чтобы LuaState был некопируемым и управлял временем жизни lua_State, тогда вы можете передавать состояние как shared_ptr<LuaState>.

...