2009-03-29 7 views
5

élément et une exception est levée lorsque de sérialisation fait l'objet en XML:Boostez la sérialisation des caractères NVP et non-XML-element

BOOST_SERIALIZATION_NVP(_member[index]) 

une solution évidente consiste à utiliser:

boost::serialization::make_nvp("ValidMemberName", _member[index]) 

Mais quelqu'un peut-il suggérer une façon de modifier coup de pouce pour cet élément illégitime les noms déclencheraient une compilatio n erreur? (Donc pas compter sur les tests unitaires pour attraper le bogue subtil ci-dessus)


Edit:

Une idée est de déclarer en quelque sorte une variable locale fictive avec le nom de l'élément passé à la macro, en supposant que l'ensemble des identifiants valides en C++ est un sous-ensemble d'éléments XML valides. Pas tout à fait sûr que cela puisse être fait cependant.

+0

Cela va générer une erreur d'exécution 'what(): nom de balise XML invalide' – alfC

Répondre

1

Je pense que votre idée fonctionnera probablement. Les identifiants C++ valides sont constitués de A-Z, a-z, 0-9 et de soulignement, qui est en fait un sous-ensemble approprié d'identifiants XML (qui ajoutent un trait d'union, un point et un groupe de caractères Unicode).

Vous pouvez essayer une construction comme celui-ci pour obtenir une erreur de compilation:

#define SAFE_BOOST_SERIALIZATION_NVP(name) \ 
    { int name = 0; } ; BOOST_SERIALZATION_NVP(name) 

Les accolades limitent la portée de la variable fictive juste que la ligne, de sorte que vous ne pas encombrer votre fonction avec des variables fausses . Probablement, le compilateur optimise aussi la variable fictive, donc il n'y a pas de coût d'exécution. Quand j'utilise cette macro dans le code suivant, je me error: invalid intializer:

#include "boost/serialization/nvp.hpp" 
#define SAFE_BOOST_SERIALIZATION_NVP(name) \ 
    { int name = 0; } ; BOOST_SERIALIZATION_NVP(name) 

int main(int argc, char *argv[]) 
{ 
    int foo[3] = { 10, 20, 30 }; 
    int bar = 10; 
    SAFE_BOOST_SERIALIZATION_NVP(foo[0]); 
    return 0; 
} 

Si je remplace foo[0] avec bar dans l'appel à SAFE_BOOST_SERIALIZATION_NVP, il compile sans erreur.

+1

Mais je ne pense pas que cela fonctionnerait lorsqu'il est utilisé dans la fonction de sérialisation. sérialiser (..) {archive & SAFE_BOOST_SER_NVP (m); } ... –

+0

@AssafLavie, vous avez raison, cependant cette légère modification (code supplémentaire à la fin) semble faire le travail: '#define SAFE_BOOST_SERIALIZATION_NVP (nom) \ BOOST_SERIALIZATION_NVP (nom); {int name = 0;} ' – alfC

2

Citant la syntaxe XML pour les noms:

NameStartChar ::= ":" | [A-Z] | "_" | [a-z] | [#xC0-#xD6] | [#xD8-#xF6] | [#xF8-#x2FF] | [#x370-#x37D] | [#x37F-#x1FFF] | [#x200C-#x200D] | [#x2070-#x218F] | [#x2C00-#x2FEF] | [#x3001-#xD7FF] | [#xF900-#xFDCF] | [#xFDF0-#xFFFD] | [#x10000-#xEFFFF] 
NameChar  ::= NameStartChar | "-" | "." | [0-9] | #xB7 | [#x0300-#x036F] | [#x203F-#x2040] 

Je vois les différences suivantes avec des noms C++: Leading _ peut être réservé en C++, en fonction de ce qui suit; les signes deux points, les points et les signes moins sont valides dans les noms XML. Les caractères Unicode peuvent également causer du chagrin en C++, mais cela dépend principalement de l'implémentation.

La partie [# x0300- # x036F] combine des accents (diacritiques), ce qui pourrait être une préoccupation supplémentaire par rapport à l'égalité des noms. Donc, il n'y a pas de solution pour attraper les caractères non-alphabétiques. < ::: /> peut ressembler à un smiley, mais c'est du XML bien formé. Pour le reste, votre idée est à peu près OK. L'idée d'Eric Melski est une belle tentative, mais elle accepte beaucoup de caractères non alphabétiques. Par exemple, foo[1], &foo, *foo, foo=0 ou foo,bar. Il y a une meilleure alternative: {using namespace name;}. Cela va accepter foo::bar, mais c'est en fait OK - foo :: bar est autorisé en XML.

+0

Mais si le' name' n'est pas déjà un espace de noms, il donnera une erreur. – alfC

1

Ceci est un hybride entre deux réponses, @Eric Melski (la plupart du temps correct --extra code doit être à la fin de define - mais solution incomplète - certains noms interdits ne sont pas "filtrés" -) et @MSalters ' La plupart du temps correct (- using namespace ne peut pas être utilisé pour des noms non déclarés arbitraires--).

Je propose d'utiliser struct:

#define SAFE_BOOST_SERIALIZATION_NVP(name) \ 
    BOOST_SERIALIZATION_NVP(name); {struct name{};} 

ou plus risquée:

#undef BOOST_SERIALIZATION_NVP 
#define BOOST_SERIALIZATION_NVP(name)        \ 
    boost::serialization::make_nvp(BOOST_PP_STRINGIZE(name), name); {struct name{};} 

Inutile de dire qu'il n'y a pas de frais d'exécution pour cela.

Questions connexes