yaml-cpp, YAML :: Node и оператор шаблона >> - PullRequest
1 голос
/ 02 ноября 2011

Я делаю какую-то сериализацию, используя yaml-cpp .Чтобы это работало, каждый класс должен объявить метод, используя сигнатуру:

template <typename T> void Serialize(T& s);

Что T - это другой класс при сохранении и загрузке.Интерфейс двух классов одинаков, но я не могу создать абстрактный базовый класс, так как большинство методов являются шаблонами.Эта часть работает правильно.Я пытался соединить его с YAML::Node operator>> и YAML::Emitter * operator<<.

Для operator<< у меня есть рабочее решение, хотя и очень жестокое.Сначала объявите суперкласс для всех сериализуемых классов:

template <typename T> class Serializable {};

Затем я могу использовать следующее operator<<:

template <typename T>
YAML::Emitter& operator<<(YAML::Emitter& out,
                          Serializable<T>& val)
{
    Serializer serializer(out);
    reinterpret_cast<T*>(&val)->Serialize(serializer);
    return out;
}

Пока это работает, хотя reinterpret_cast выглядит довольнострашно, и я не уверен, что это даже законно.Я попробовал то же самое для operator>>, но это не сработало.Это выглядит так:

template <typename T>
void operator>>(const YAML::Node& node,
                Serializable<T>& val)
{
    Deserializer deserializer(node);
    reinterpret_cast<T*>(&val)->Serialize(deserializer);
}

Но gcc (4.6.2) и clang (2.9) игнорируют его и используют operator>>, определенный в nodeimp.h (часть yaml-cpp):

template <typename T>
inline void operator >> (const Node& node, T& value) {
    if(!ConvertScalar(node, value))
        throw InvalidScalar(node.m_mark);
}

Итак, мой вопрос: как мне это решить?Вещь, которую я абсолютно хочу, это иметь только один метод для сериализации и десериализации, и иметь возможность использовать >> и <<, как если бы это был обычный тип, поддерживаемый yaml-cpp. </p>

1 Ответ

0 голосов
/ 02 ноября 2011

Во-первых, о reinterpret_cast: вы действительно хотите static_cast. В вашем случае вы знаете, что val - это a T (а не просто Serializable<T>), поэтому вы можете разыграть его напрямую.

Здесь я предполагаю, что вы объявляете свои классы как

class Foo: public Serializable<Foo> { ... };

reinterpret_cast будет интерпретировать байтов из val как T, который не гарантированно работает, но, вероятно, работает в вашем случае, потому что у вас есть одиночное наследование, а Serializable<T> не не добавлять переменные-члены.

Далее, к вашей реальной проблеме: это ошибка в yaml-cpp, и она теперь исправлена ​​( r52790a15757d , если вы не отставали от репозитория mercurial, и смотрите http://code.google.com/p/yaml-cpp/issues/detail?id=126 за вопрос, который я открыл).

С учетом вышеприведенного исправления, я полагаю, ваш код должен работать. Если вы не поспеваете за репозиторием, тогда разница довольно мала - вы можете исправить это в своей версии yaml-cpp.

...