2009-03-29 13 views
5

Wenn Sie das Makro BOOST_SERIALIZATION_NVP verwenden, um ein Name-Wert-Paar für die XML-Serialisierung zu erstellen, ermöglicht der Compiler die Kompilierung des folgenden Codes, obwohl der Elementname kein gültiges XML ist Element und ein Ausnahme ausgelöst wird, wenn tatsächlich versuchen, um das Objekt in XML zu serialisiert:Boost-Serialisierung NVP-Makro- und Nicht-XML-Element Zeichen

BOOST_SERIALIZATION_NVP(_member[index]) 

eine offensichtliche Lösung ist, zu verwenden:

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

Aber kann jemand empfehlen, einen Weg Schub zu modifizieren, so dass illegitimes Element Namen würden eine Kompilation auslösen n Fehler? (Also nicht auf Unit-Tests verlassen, um die oben subtilen Fehler zu fangen)


Edit:

Eine Idee ist irgendwie eine Dummy-lokale Variable mit dem Namen des an das Makro übergeben Element zu deklarieren, Angenommen, der Satz gültiger Bezeichner in C++ ist eine Teilmenge gültiger XML-Elemente. Nicht ganz sicher, aber das kann getan werden.

+0

Dies erzeugt einen Laufzeitfehler 'what(): Ungültiger XML-Tag-Name' – alfC

Antwort

1

Ich denke, Ihre Idee wird wahrscheinlich funktionieren. Gültige C++ - Bezeichner bestehen aus A-Z, a-z, 0-9 und Unterstrich, was tatsächlich eine richtige Teilmenge von XML-Bezeichnern ist (die dem Satz einen Bindestrich, einen Punkt und eine Menge Unicode-Zeichen hinzufügen).

Sie könnten ein Konstrukt wie diese versuchen, eine Kompilierung Fehler zu erhalten:

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

Die Streben begrenzen den Umfang der Dummy-Variable nur diese Linie, so dass Sie Ihre Funktion mit falschen Variablen nicht Krempel . Wahrscheinlich optimiert der Compiler auch die Dummy-Variable, so dass keine Laufzeitkosten entstehen. Als ich dieses Makro in dem folgenden Code verwenden, ich error: invalid intializer erhalten:

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

Wenn ich foo[0] mit bar im Aufruf von SAFE_BOOST_SERIALIZATION_NVP ersetzen, kompiliert es ohne Fehler.

+1

Aber ich denke nicht, dass es funktionieren würde, wenn in der Serialisierungsfunktion verwendet. Serialisierung (..) {Archiv & SAFE_BOOST_SER_NVP (m); } ... –

+0

@AssafLavie, Sie haben Recht, jedoch scheint diese leichte Änderung (zusätzlicher Code am Ende) den Job zu machen: '#define SAFE_BOOST_SERIALIZATION_NVP (name) \ BOOST_SERIALIZATION_NVP (name); {int name = 0;} ' – alfC

2

die XML-Syntax für Namen Zitiert:

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] 

ich folgende Unterschiede mit C++ Namen sehen: Führende _ können in C++ reserviert werden, je nachdem, was folgt; Doppelpunkte, Punkte und Minuszeichen sind in XML-Namen gültig. Unicode-Zeichen können in C++ auch etwas Kummer verursachen, aber das ist meistens von der Implementierung abhängig.

Der Teil [# x0300- # x036F] kombiniert Akzente (diakritische Zeichen), die ein zusätzliches Problem hinsichtlich der Gleichheit von Namen sein könnten.

Also, es gibt keine Lösung, die die nicht alphabetischen Zeichen abfängt. < ::: /> kann wie ein Smiley aussehen, aber es ist wohlgeformtes XML. Für den Rest ist deine Idee ziemlich in Ordnung. Eric Melskis Idee ist ein schöner Versuch, aber er akzeptiert viele nicht-alphabetische Zeichen. Zum Beispiel foo[1], &foo, , foo=0 oder foo,bar. Es gibt eine bessere Alternative: {using namespace name;}. Dies wird foo::bar akzeptieren, aber das ist eigentlich OK - foo :: bar ist in XML erlaubt.

+0

Wenn der' name' jedoch nicht bereits ein Namespace ist, wird ein Fehler ausgegeben. – alfC

1

Dies ist ein Hybrid zwischen zwei Antworten, @Eric Melski (meistens richtig --Extra-Code muss am Ende von sein - aber unvollständige Lösung - einige verbotene Namen sind nicht "gefiltert" -) und @MSalters ' meistens korrekt (- using namespace kann nicht für beliebige nicht deklarierte Namen verwendet werden--).

Ich schlage vor, mit struct:

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

oder riskanter:

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

Unnötig zu sagen, dass es keine Laufzeit Kosten hierfür ist.