ускорить сериализацию макроса NVP и не-XML-элементов - PullRequest
5 голосов
/ 29 марта 2009

При использовании макроса BOOST_SERIALIZATION_NVP для создания пары имя-значение для сериализации XML компилятор с радостью позволяет компилировать следующий код, даже если имя элемента не является допустимым элементом XML и при попытке выдается исключение фактически сериализовать объект в XML:

BOOST_SERIALIZATION_NVP(_member[index])

Очевидным решением является использование:

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

Но может ли кто-нибудь предложить способ изменить boost, чтобы незаконные имена элементов вызывали ошибку компиляции? (таким образом, не полагаясь на юнит-тестирование, чтобы поймать вышеупомянутую тонкую ошибку)


Edit:

Одна идея состоит в том, чтобы как-то объявить фиктивную локальную переменную с именем элемента, передаваемого макросу, предполагая, что набор допустимых идентификаторов в C ++ является подмножеством допустимых элементов XML. Не совсем уверен, что это может быть сделано, хотя.

Ответы [ 3 ]

2 голосов
/ 06 апреля 2009

Цитирование синтаксиса XML для имен:

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]

Я вижу следующие различия с именами C ++: ведущий _ может быть зарезервирован в C ++, в зависимости от того, что следует; двоеточия, точки и знаки минуса допустимы в именах XML. Символы Unicode также могут вызвать некоторое горе в C ++, но это в основном зависит от реализации.

Часть [# x0300- # x036F] объединяет акценты (диакритические знаки), что может быть дополнительной проблемой при равенстве имен.

Итак, нет решения, которое ловит не алфавитные символы. <::: /> может выглядеть как смайлик, но это правильно сформированный XML. В остальном, ваша идея в значительной степени в порядке. Идея Эрика Мелски - хорошая попытка, но она принимает много неалфавитных символов. Например, foo[1], &foo, *foo, foo=0 или foo,bar. Есть лучшая альтернатива: {using namespace name;}. Это примет foo::bar, но на самом деле это нормально - foo :: bar разрешен в XML.

1 голос
/ 01 сентября 2014

Это гибрид двух ответов: @Eric Melski (в основном правильный - дополнительный код должен быть в конце define - но неполное решение - некоторые запрещенные имена не «фильтруются» -) и @MSalters 'в основном правильно (- using namespace нельзя использовать для произвольных необъявленных имен -).

Я предлагаю использовать struct:

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

или более рискованно:

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

Само собой разумеется, что для этого нет времени выполнения.

1 голос
/ 31 марта 2009

Я думаю, что ваша идея, вероятно, будет работать. Допустимые идентификаторы C ++ состоят из A-Z, a-z, 0-9 и подчеркивания, что на самом деле является надлежащим подмножеством идентификаторов XML (которые добавляют дефис, точку и набор символов Unicode в набор).

Вы можете попробовать такую ​​конструкцию, чтобы получить ошибку времени компиляции:

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

Скобки ограничивают область действия фиктивной переменной только этой строкой, поэтому вы не загромождаете свою функцию фиктивными переменными. Вероятно, компилятор также оптимизирует фиктивную переменную, поэтому нет затрат времени выполнения. Когда я использую этот макрос в следующем коде, я получаю 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;
}

Если я заменю foo[0] на bar при вызове SAFE_BOOST_SERIALIZATION_NVP, он компилируется без ошибок.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...