更改名称空间以自定义boost xml的标记名称后的反序列化问题

时间:2017-04-01 17:45:37

标签: c++ xml boost boost-serialization

我已对以下更改进行了标记的自定义名称。 以下代码更改成功,我可以创建一个带有自定义名称的xml文档。

namespace boost { namespace serialization {
    template <typename Ar>
        void serialize(Ar& ar,std::pair<int const , Myclass::Pgroups>& p, unsigned) {
            ar & make_nvp("assetid", p.first) & make_nvp("assetdata", p.second);
        }
} }

namespace boost { namespace serialization {
    template <typename Ar>
        void serialize(Ar& ar,std::pair<int const , values>& p, unsigned) {
            ar & make_nvp("hacc_groupid", p.first) & make_nvp("hacc_groupdata", p.second);
        }
} }

但这似乎是将xml反序列化到对象的问题,我得到了提升错误

 template<class Archive, class Object>
   std::string serialise_to_string(const char* tag,Object & obj)
   {
     std::ostringstream os (std::ios::binary);
     Archive arch ( os );
     arch << boost::serialization::make_nvp(tag,obj);
     return os.str();
   }
   template<class Archive , class Object>
   void deserialise_to_obj( std::string const  &s1,Object &outObj)
   {
      std::stringstream is( s1, std::ios_base::binary| std::ios_base::out| std::ios_base::in);
      Archive arch (is);
      arch >> boost::serialization::make_nvp("tag",outObj);
   };
  

如果没有boost命名空间自定义,序列化和反序列化就可以完美地工作,但是为了具有自定义标记名称,boost命名空间发生了变化,反序列化有问题。

上述代码出错,即命名空间arg void serialize(Ar& ar,std::pair<int const , values>& p, unsigned)

中的const
In file included from main.cpp:1:
In file included from /usr/local/include/boost/archive/binary_oarchive.hpp:21:
In file included from /usr/local/include/boost/archive/binary_oarchive_impl.hpp:22:
In file included from /usr/local/include/boost/archive/basic_binary_oarchive.hpp:33:
In file included from /usr/local/include/boost/archive/detail/common_oarchive.hpp:22:
In file included from /usr/local/include/boost/archive/detail/interface_oarchive.hpp:23:
In file included from /usr/local/include/boost/archive/detail/oserializer.hpp:68:
/usr/local/include/boost/archive/detail/check.hpp:162:5: error: static_assert failed "typex::value"
    BOOST_STATIC_ASSERT(typex::value);
    ^                   ~~~~~~~~~~~~
/usr/local/include/boost/static_assert.hpp:70:41: note: expanded from macro 'BOOST_STATIC_ASSERT'
#     define BOOST_STATIC_ASSERT( ... ) static_assert(__VA_ARGS__, #__VA_ARGS__)
                                        ^             ~~~~~~~~~~~
/usr/local/include/boost/archive/detail/iserializer.hpp:603:13: note: in instantiation of function template specialization 'boost::archive::detail::check_const_loading<const int>' requested here
    detail::check_const_loading< T >();
            ^
/usr/local/include/boost/archive/detail/common_iarchive.hpp:66:18: note: in instantiation of function template specialization 'boost::archive::load<boost::archive::xml_iarchive, const int>' requested here
        archive::load(* this->This(), t);
                 ^
/usr/local/include/boost/archive/basic_xml_iarchive.hpp:78:39: note: in instantiation of function template specialization 'boost::archive::detail::common_iarchive<boost::archive::xml_iarchive>::load_override<const int>' requested here
        this->detail_common_iarchive::load_override(t.value());
                                      ^
/usr/local/include/boost/archive/xml_iarchive.hpp:95:38: note: in instantiation of function template specialization 'boost::archive::basic_xml_iarchive<boost::archive::xml_iarchive>::load_override<const int>' requested here
        basic_xml_iarchive<Archive>::load_override(t);
                                     ^
/usr/local/include/boost/archive/detail/interface_iarchive.hpp:68:23: note: in instantiation of function template specialization 'boost::archive::xml_iarchive_impl<boost::archive::xml_iarchive>::load_override<const boost::serialization::nvp<const int> >' requested here
        this->This()->load_override(t);
                      ^
/usr/local/include/boost/archive/detail/interface_iarchive.hpp:75:32: note: (skipping 45 contexts in backtrace; use -ftemplate-backtrace-limit=0 to see all)
        return *(this->This()) >> t;
                               ^
/usr/local/include/boost/archive/basic_xml_iarchive.hpp:78:39: note: in instantiation of function template specialization 'boost::archive::detail::common_iarchive<boost::archive::xml_iarchive>::load_override<Myclass>' requested here
        this->detail_common_iarchive::load_override(t.value());
                                      ^
/usr/local/include/boost/archive/xml_iarchive.hpp:95:38: note: in instantiation of function template specialization 'boost::archive::basic_xml_iarchive<boost::archive::xml_iarchive>::load_override<Myclass>' requested here
        basic_xml_iarchive<Archive>::load_override(t);
                                     ^
/usr/local/include/boost/archive/detail/interface_iarchive.hpp:68:23: note: in instantiation of function template specialization 'boost::archive::xml_iarchive_impl<boost::archive::xml_iarchive>::load_override<const boost::serialization::nvp<Myclass> >' requested here
        this->This()->load_override(t);
  

如果从boost命名空间,deserialise_to_obj和serialise_to_string函数中删除了const-ness,则代码编译并运行没有任何问题,但不会自定义标记名称

希望我的信息清楚, Iam坚持一个问题,我不确定对象的反序列化是否可以顺利发生自定义标签名称。 请告诉我必须做什么

使用自定义标记名称live at coliru

进行序列化和反序列化的示例代码

示例没有反序列化的工作代码和自定义标记名称 live at coliru

由于 特加斯

1 个答案:

答案 0 :(得分:2)

cinch在std::pair<>::first的{​​{1}}的常数内。

这是使用std::map::value_type有意义的极少数情况之一:

const_cast

顺便提一下,这也是Boost序列化的作用:http://www.boost.org/doc/libs/1_63_0/boost/serialization/utility.hpp

完整工作演示

  

已更新:此时还会覆盖namespace boost { namespace serialization { template<class Ar> inline void serialize(Ar & ar, std::pair<int const, values> & p, unsigned) { ar & make_nvp("assetid", const_cast<int&>(p.first)) & make_nvp("assetdata", p.second); } template <typename Ar> void serialize(Ar& ar,std::pair<int const, Myclass::Pgroups>& p, unsigned) { ar & make_nvp("hacc_groupid", const_cast<int&>(p.first)) & make_nvp("hacc_groupdata", p.second); } } } 节点名称

<强> Live On Coliru

item

打印

#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/xml_oarchive.hpp>
#include <boost/archive/xml_iarchive.hpp>

#include <boost/archive/binary_iarchive.hpp>
#include <boost/serialization/binary_object.hpp>
#include <boost/serialization/serialization.hpp>
#include <boost/serialization/nvp.hpp>
#include <iostream>
#include <string>
#include <iomanip>
#include <sstream>
#include <fstream>

#include <map>
#include <boost/serialization/map.hpp>
#include <boost/serialization/split_member.hpp>

using boost::serialization::make_nvp;

namespace MyDomain { // demonstrate ADL for serialize
    struct values
    {
        std::string name;
        std::string sex;
        values() : name("dummy"), sex("dummy") {};

        template<class Archive>   
            void serialize(Archive & ar, const unsigned int /*version*/) {
                ar & make_nvp("name", name);
                ar & make_nvp("sex", sex);
            }
    };

    struct Myclass {
        Myclass() { }

        template<class Archive>
            void serialize(Archive & ar, const unsigned int /*version*/)  {
                ar & make_nvp("etoto", e_group);
                ar & make_nvp("ptoto", p_group);
            }

        typedef std::map<int,values> groups;
        typedef std::map<int,groups> Pgroups;    

        groups  e_group;
        Pgroups p_group;
    };

    #define CUSTOM_MAP_SERIALIZE(Map, keyname, valuename) \
    template<class Ar> inline void serialize(Ar & ar, Map::value_type& p, unsigned) { \
            ar & make_nvp(keyname, const_cast<int&>(p.first)) & make_nvp(valuename, p.second); \
        }

    CUSTOM_MAP_SERIALIZE(Myclass::groups, "assetid", "assetdata")
    CUSTOM_MAP_SERIALIZE(Myclass::Pgroups, "hacc_groupid", "hacc_groupdata")
}

namespace boost { namespace serialization {

    #define OVERRIDE_NVP(T, name) \
       template <> inline const nvp<T> make_nvp(const char *, T &t) { return nvp<T>(name, t); } \
       template <> inline const nvp<T const> make_nvp(const char *, T const &t) { return nvp<T const>(name, t); }

    OVERRIDE_NVP(MyDomain::Myclass::groups::value_type,  "group_item")
    OVERRIDE_NVP(MyDomain::Myclass::Pgroups::value_type, "Pgroup_item")

    #undef OVERRIDE_NVP
} }

template<class Archive, class Object>
std::string serialise_to_string(Object const& assetlist)
{
    auto os = std::ostringstream(std::ios::binary);
    Archive arch { os, boost::archive::no_header };
    arch << make_nvp("Main", assetlist);
    return os.str();
}


template<class Archive , class Object>
void deserialise_to_obj(std::string const &s1,Object &outObj)
{
    std::stringstream is( s1, std::ios_base::binary| std::ios_base::out| std::ios_base::in);
    Archive arch { is, boost::archive::no_header };
    arch >> make_nvp("Main", outObj);
}

MyDomain::Myclass create_data()
{
    MyDomain::Myclass object;
    MyDomain::values val1;
    object.e_group.insert( std::make_pair(1,val1) ) ;
    object.e_group.insert( std::make_pair(2,val1) ) ;
    object.p_group.insert( std::make_pair(1,object.e_group) ) ;
    object.p_group.insert( std::make_pair(2,object.e_group) ) ;   
    return object;
}

int main() {
    {
        MyDomain::Myclass obj = create_data() ;

        std::string s2 = serialise_to_string<boost::archive::xml_oarchive>(obj);

        //Save xml to a file
        {
            std::ofstream ofs("output1.xml");
            ofs << s2 << std::endl << std::endl;
            ofs.close();
        }

    }

    std::string content;
    {
        std::ifstream ifs("output1.xml");
        content.assign(std::istreambuf_iterator<char>(ifs), {});
        ifs.close();
    }
    {
        MyDomain::Myclass outObj;
        deserialise_to_obj<boost::archive::xml_iarchive>(content,outObj);
        //Print the object 
        for(auto &i:outObj.p_group){
            std::cout<<"\n"<<i.first<<"\n";
            for(auto &j:i.second){
                std::cout<<"\t"<<j.first<<"\t"<<j.second.name<<"\t"<<j.second.sex<<"\n";
            }
        }  
    }
}

使用output1.xml

1
    1   dummy   dummy
    2   dummy   dummy

2
    1   dummy   dummy
    2   dummy   dummy