shared_ptr requer tipo completo; não pode usá -lo com lua_state*
-
19-09-2019 - |
Pergunta
Estou escrevendo um invólucro C ++/OOP para Lua. Meu código é:
class LuaState
{
boost::shared_ptr<lua_State> L;
LuaState(): L( luaL_newstate(), LuaState::CustomDeleter )
{
}
}
O problema é que Lua_state é tipo incompleto e o construtor shared_ptr requer tipo completo. E eu preciso de compartilhamento de ponteiro seguro. (Os documentos engraçados do Boost dizem que a maioria das funções não requer tipo completo, mas o construtor exige, portanto, não há como usá -lo. http://www.boost.org/doc/libs/1_42_0/libs/smart_ptr/smart_ptr.htm)
Posso resolver isso? Obrigada.
Solução
Você está usando seu próprio Deleter, o que significa que não precisa ter um tipo completo de construção. O único requisito é que CustomDeleter
pode lidar com isso. (pode converter o ponteiro que passou para um tipo completo, por exemplo (digamos, de void*
para CompleteType*
).
O pano de fundo da integridade é que, uma vez que o construtor de shared_ptr
é chamado com o deleter padrão, ele instanciará uma classe que contém a linha delete p;
- e para que este código esteja correto, p
não deve estar incompleto. O destruidor chamará esse código deleter indiretamente, para que não dependa da integridade do tipo.
No entanto, se você aprovar seu próprio Deleter, os requisitos do seu próprio Deleter serão aplicados. Certifique -se de definir CustomDeleter
depois lua_State
foi concluído.
Outras dicas
Parecia estranho que boost::shared_ptr
exigiria um tipo completo de instanciação, então escrevi este pequeno teste pequeno que demonstra o oposto (código no final).
Eu acredito que o problema não está com o tipo que precisa ser completo, mas com o segundo argumento de que você está passando para o shared_ptr
construtor, que parece uma função de membro. O segundo argumento deve ser algo chamável com um único argumento de ponteiro. Se você deseja usar uma função de membro do seu invólucro, você pode usar boost::bind
Para adaptar a interface.
Talvez você quis dizer?:
LuaState(): L( luaL_newstate(), boost::bind(LuaState::CustomDeleter,this,_1) )
{
}
Demonstração que boost::shared_ptr
não requer tipos completos:
// 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;
}
Dado que um lua_state* não pode ser clonado, copiando um objeto Luastate significativo? Quais são a semântica esperada de copiar um objeto inerentemente incomparável?
O comportamento que você parece querer é cópia superficial - e a melhor maneira de fazer isso é que o Luastate seja incomparável e gerencie a vida inteira do Lua_state, então você pode passar pelo estado como um shared_ptr<LuaState>
.