0

C++11 シリアル化ライブラリであるcerealを使用しています。これがライブラリのバグなのか、それとも私の使用方法の問題なのかはわかりません。サポートが必要です。

私自身のコードを代表する (しかし依存していない) 次の最小限の再現を考えると、JSONInputArchive::search から例外がスローされます。

私は現在、この github reproで 436a0a275cda007f137876f37b4fc8783e615352 をコミットしています (執筆時点では、開発ブランチの先端です。)

#include <iostream>
#include <sstream>
#include <string>
#include <map>

#include "cereal/cereal.hpp"
#include "cereal/types/map.hpp"
#include "cereal/types/vector.hpp"
#include "cereal/types/memory.hpp"
#include "cereal/types/string.hpp"
#include "cereal/types/base_class.hpp"

#include "cereal/archives/json.hpp"
#include <cereal/types/polymorphic.hpp>

class BaseClass : public std::enable_shared_from_this<BaseClass> {
public:
    virtual ~BaseClass(){}

    template <class Archive>
    void serialize(Archive & archive){
        archive(CEREAL_NVP(name), CEREAL_NVP(baseMember));
    }
protected:
    BaseClass(const std::string &a_name):
        name(a_name){
    }

    std::string name;
    int baseMember; //let this have random junk so we can see if it saves right.
};

class DerivedClass : public BaseClass {
    friend cereal::access;
public:
    static std::shared_ptr<DerivedClass> make(const std::string &a_name, int a_derivedMember){
        return std::shared_ptr<DerivedClass>(new DerivedClass(a_name, a_derivedMember));
    }

    template <class Archive>
    void serialize(Archive & archive){
        archive(CEREAL_NVP(derivedMember), cereal::make_nvp("base", cereal::base_class<BaseClass>(this)));
    }
private:
    DerivedClass(const std::string &a_name, int a_derivedMember):
        BaseClass(a_name),
        derivedMember(a_derivedMember){
    }

    template <class Archive>
    static DerivedClass * load_and_allocate(Archive &archive){
        int derivedMember;
        archive(CEREAL_NVP(derivedMember)); //breaks here.
        DerivedClass* object = new DerivedClass("", derivedMember);
        archive(cereal::make_nvp("base", cereal::base_class<BaseClass>(object)));
        return object;
    }

    int derivedMember;
};

CEREAL_REGISTER_TYPE(DerivedClass);

void saveTest(){
    std::stringstream stream;
    {
        cereal::JSONOutputArchive archive(stream);
        auto testSave = DerivedClass::make("TestName", 4);
        archive(cereal::make_nvp("test", testSave));
    }
    std::cout << stream.str() << std::endl;
    std::shared_ptr<DerivedClass> loaded;
    {
        cereal::JSONInputArchive archive(stream);
        archive(cereal::make_nvp("test", loaded));
    }
    std::stringstream stream2;
    {
        cereal::JSONOutputArchive archive(stream2);
        archive(cereal::make_nvp("test", loaded));
    }
    std::cout << stream2.str() << std::endl;
    std::cout << "TA-DA!" << std::endl;
}

int main(){
    saveTest();
}

上記から取得したサンプル出力 (例外の前) は次のとおりです。

{
    "test": {
        "id": 1073741824,
        "ptr_wrapper": {
            "id": 2147483649,
            "data": {
                "derivedMember": 4,
                "base": {
                    "name": "TestName",
                    "baseMember": -1163005939
                }
            }
        }
    }
}

問題をデバッグするために、throwing メソッド (cereal/archive/json.hpp 内) を変更して、検索対象と検索対象の各値を出力しました。ここに私の修正版があります:

  //! Adjust our position such that we are at the node with the given name
  /*! @throws Exception if no such named node exists */
  inline void search( const char * searchName )//, GenericValue const & parent )
  {
    size_t index = 0;
    std::cout << "_____" << std::endl;
    for( auto it = itsMemberItBegin; it != itsMemberItEnd; ++it, ++index )
      if( std::strcmp( searchName, it->name.GetString() ) == 0 )
      {
        itsIndex = index;
        return;
      } else{
          //I added this part here
          std::cout << "!" << searchName << " == " << it->name.GetString() << std::endl;
      }

    throw Exception("JSON Parsing failed - provided NVP not found");
  }

例外の前の上記のメソッドの出力:

!derivedMember == id
!derivedMember == data

これから得られる出力は、検索が「test.ptr_wrapper.data」ではなく「test.ptr_wrapper」のメンバーを調べていることを示しているようです。

私の質問はこれです: 私は何か間違ったことをしていますか? それとも穀物に問題がありますか?

4

1 に答える 1