Question

J'écris un wrapper C ++ / POO pour Lua. Mon code est:

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

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

Le problème est lua_State est un type incomplet et constructeur shared_ptr exige type complet. Et je partage besoin de pointeur en toute sécurité. (Boost chose drôle docs disent que la plupart des fonctions ne nécessitent pas de type complet, mais le constructeur a besoin, donc il n'y a aucun moyen de l'utiliser. http://www.boost.org/doc/libs/1_42_0/libs/smart_ptr/smart_ptr.htm )

Puis-puis-je résoudre ce problème? Merci.

Était-ce utile?

La solution

Vous utilisez votre propre Deleter, ce qui signifie que vous ne devez pas avoir un type complet sur la construction. La seule exigence est que CustomDeleter peut gérer cela. (Il peut convertir le pointeur passé à un type complet, par exemple (par exemple, de void* à CompleteType*).

L'arrière-plan de l'exhaustivité est qu'une fois que le constructeur de shared_ptr est appelée avec le Deleter par défaut, il instancier une classe qui contient la ligne delete p; - et que ce code soit correct, p ne doit pas être incomplètes. Le destructor appellera ce code Deleter indirectement, il ne dépend pas de l'intégralité du type.

Toutefois, si vous passez votre propre Deleter, les exigences de votre propre Deleter s'appliqueront. Assurez-vous de définir CustomDeleter après lua_State est devenu terminé.

Autres conseils

Il semblait étrange que boost::shared_ptr nécessiterait un type complet pour instanciation, donc je l'ai écrit ce petit petit test qui démontrent le contraire (code à la fin).

Je crois que le problème est pas avec le type besoin d'être complète, mais avec le deuxième argument que vous passez au constructeur de shared_ptr, qui ressemble à une fonction membre. Le second argument doit être quelque chose appelable avec un seul argument pointeur. Si vous souhaitez utiliser une fonction de membre de votre emballage, vous pouvez utiliser boost::bind pour adapter l'interface.

Peut-être que vous vouliez dire:

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

Démonstration que boost::shared_ptr ne nécessite pas les types complets:

// 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;
}

Étant donné que lua_State * ne peut pas être cloné, est la copie d'un objet LuaState significatif? Quelles sont la sémantique attendue de la copie d'un tel objet en soi incopiables?

Le comportement que vous semblez vouloir est copie superficielle - et la meilleure façon de le faire est pour LuaState être incopiables et gérer la durée de vie du lua_State vous pouvez alors passer autour de l'état en tant que shared_ptr<LuaState> .

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top