Shared_ptr требует полного типа;невозможно использовать его с lua_State*

StackOverflow https://stackoverflow.com/questions/2433667

  •  19-09-2019
  •  | 
  •  

Вопрос

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

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

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

Проблема в том, что lua_State имеет неполный тип, а конструкторуshared_ptr требуется полный тип.И мне нужен безопасный обмен указателями.(Забавно, что в документации по Boost говорится, что большинству функций не требуется полный тип, но требуется конструктор, поэтому его невозможно использовать. 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 стал завершенным.

Другие советы

Казалось странным, что 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;
}

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top