序列化所需的公共空构造函数

时间:2017-06-30 12:43:30

标签: c++ serialization boost

我正在追逐一只兔子,试图找出以下内容:

  1. 我不想要空的公共构造函数(它们可以,并且会产生问题)
  2. 两个模板类必须保持彼此无知,否则我将有模板参数循环问题
  3. 第三类显然需要访问以前的两个类,因为它是(de)序列化的类
  4. 缩小的例子如下所示:

    template <class s_trait>
    class state
    {
    public:
        state(s_trait);
    private:
        state() = default;
        friend class boost::serialization::access;
        template <typename archive>
        void serialize(archive &, const unsigned int);
    };
    
    template <class a_trait>
    class action
    {
    public:
        action(a_trait);
    private:
        action() = default;
        friend class boost::serialization::access;
        template <typename archive>
        void serialize(archive &, const unsigned int);
    };
    
    template <class state_type, class action_type>
    class policy
    {
    public:
         /// ... some public methods
    private:
        friend class boost::serialization::access;
        std::unordered_map<state_class,
                           std::unordered_map<action_class,
                                              double>> __policies__;
        template <typename archive>
        void serialize(archive &, const unsigned int);
    };
    

    上述骨架(没有枯燥的细节)有以下设计问题:

      如果要了解状态,则
    • state无法识别操作
    • 班级action无法了解state,反之亦然
    • policy模板stateaction有意

    然而,使用这些类编译应用程序会产生std :: pair引起的问题,这似乎源于boost :: serialization :: access,而这似乎来自于类policy需要的事实调用serialize时访问默认的空构造函数:

    /usr/include/c++/5/bits/stl_pair.h: In instantiation of ‘constexpr std::pair<_T1, _T2>::pair() [with _T1 = const relearn::state<mumbler::state<std::__cxx11::basic_string<char> > >; _T2 = std::unordered_map<relearn::action<mumbler::action<std::__cxx11::basic_string<char> > >, double, relearn::hasher<relearn::action<mu
    mbler::action<std::__cxx11::basic_string<char> > > >, std::equal_to<relearn::action<mumbler::action<std::__cxx11::basic_string<char> > > >, std::allocator<std::pair<const relearn::action<mumbler::action<std::__cxx11::basic_string<char> > >, double> > >]’:
    /usr/include/boost/serialization/access.hpp:132:9:   required from ‘static void boost::serialization::access::construct(T*) [with T = std::pair<const relearn::state<mumbler::state<std::__cxx11::basic_string<char> > >, std::unordered_map<relearn::action<mumbler::action<std::__cxx11::basic_string<char> > >, double, rel
    earn::hasher<relearn::action<mumbler::action<std::__cxx11::basic_string<char> > > >, std::equal_to<relearn::action<mumbler::action<std::__cxx11::basic_string<char> > > >, std::allocator<std::pair<const relearn::action<mumbler::action<std::__cxx11::basic_string<char> > >, double> > > >]’
    /usr/include/boost/serialization/serialization.hpp:93:22:   required from ‘void boost::serialization::load_construct_data(Archive&, T*, unsigned int) [with Archive = boost::archive::binary_iarchive; T = std::pair<const relearn::state<mumbler::state<std::__cxx11::basic_string<char> > >, std::unordered_map<relearn::act
    ion<mumbler::action<std::__cxx11::basic_string<char> > >, double, relearn::hasher<relearn::action<mumbler::action<std::__cxx11::basic_string<char> > > >, std::equal_to<relearn::action<mumbler::action<std::__cxx11::basic_string<char> > > >, std::allocator<std::pair<const relearn::action<mumbler::action<std::__cxx11::b
    asic_string<char> > >, double> > > >]’
    /usr/include/boost/serialization/serialization.hpp:158:28:   required from ‘void boost::serialization::load_construct_data_adl(Archive&, T*, unsigned int) [with Archive = boost::archive::binary_iarchive; T = std::pair<const relearn::state<mumbler::state<std::__cxx11::basic_string<char> > >, std::unordered_map<relearn
    ::action<mumbler::action<std::__cxx11::basic_string<char> > >, double, relearn::hasher<relearn::action<mumbler::action<std::__cxx11::basic_string<char> > > >, std::equal_to<relearn::action<mumbler::action<std::__cxx11::basic_string<char> > > >, std::allocator<std::pair<const relearn::action<mumbler::action<std::__cxx
    11::basic_string<char> > >, double> > > >]’
    /usr/include/boost/serialization/detail/stack_constructor.hpp:54:54:   required from ‘boost::serialization::detail::stack_construct<Archive, T>::stack_construct(Archive&, unsigned int) [with Archive = boost::archive::binary_iarchive; T = std::pair<const relearn::state<mumbler::state<std::__cxx11::basic_string<char> >
     >, std::unordered_map<relearn::action<mumbler::action<std::__cxx11::basic_string<char> > >, double, relearn::hasher<relearn::action<mumbler::action<std::__cxx11::basic_string<char> > > >, std::equal_to<relearn::action<mumbler::action<std::__cxx11::basic_string<char> > > >, std::allocator<std::pair<const relearn::act
    ion<mumbler::action<std::__cxx11::basic_string<char> > >, double> > > >]’
    /usr/include/boost/serialization/unordered_map.hpp:45:55:   required from ‘void boost::serialization::stl::archive_input_unordered_map<Archive, Container>::operator()(Archive&, Container&, unsigned int) [with Archive = boost::archive::binary_iarchive; Container = std::unordered_map<relearn::state<mumbler::state<std::
    __cxx11::basic_string<char> > >, std::unordered_map<relearn::action<mumbler::action<std::__cxx11::basic_string<char> > >, double, relearn::hasher<relearn::action<mumbler::action<std::__cxx11::basic_string<char> > > >, std::equal_to<relearn::action<mumbler::action<std::__cxx11::basic_string<char> > > >, std::allocator
    <std::pair<const relearn::action<mumbler::action<std::__cxx11::basic_string<char> > >, double> > >, relearn::hasher<relearn::state<mumbler::state<std::__cxx11::basic_string<char> > > >, std::equal_to<relearn::state<mumbler::state<std::__cxx11::basic_string<char> > > >, std::allocator<std::pair<const relearn::state<mu
    mbler::state<std::__cxx11::basic_string<char> > >, std::unordered_map<relearn::action<mumbler::action<std::__cxx11::basic_string<char> > >, double, relearn::hasher<relearn::action<mumbler::action<std::__cxx11::basic_string<char> > > >, std::equal_to<relearn::action<mumbler::action<std::__cxx11::basic_string<char> > >
     >, std::allocator<std::pair<const relearn::action<mumbler::action<std::__cxx11::basic_string<char> > >, double> > > > > >]’
    /usr/include/boost/serialization/unordered_collections_load_imp.hpp:66:14:   [ skipping 24 instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ]
    /usr/include/boost/archive/detail/iserializer.hpp:618:18:   required from ‘void boost::archive::load(Archive&, T&) [with Archive = boost::archive::binary_iarchive; T = relearn::policy<relearn::state<mumbler::state<std::__cxx11::basic_string<char> > >, relearn::action<mumbler::action<std::__cxx11::basic_string<char> >
     > >]’
    /usr/include/boost/archive/detail/common_iarchive.hpp:66:22:   required from ‘void boost::archive::detail::common_iarchive<Archive>::load_override(T&, int) [with T = relearn::policy<relearn::state<mumbler::state<std::__cxx11::basic_string<char> > >, relearn::action<mumbler::action<std::__cxx11::basic_string<char> > >
     >; Archive = boost::archive::binary_iarchive]’
    /usr/include/boost/archive/basic_binary_iarchive.hpp:76:7:   required from ‘void boost::archive::basic_binary_iarchive<Archive>::load_override(T&, int) [with T = relearn::policy<relearn::state<mumbler::state<std::__cxx11::basic_string<char> > >, relearn::action<mumbler::action<std::__cxx11::basic_string<char> > > >; 
    Archive = boost::archive::binary_iarchive]’
    /usr/include/boost/archive/binary_iarchive_impl.hpp:62:9:   required from ‘void boost::archive::binary_iarchive_impl<Archive, Elem, Tr>::load_override(T&, int) [with T = relearn::policy<relearn::state<mumbler::state<std::__cxx11::basic_string<char> > >, relearn::action<mumbler::action<std::__cxx11::basic_string<char>
     > > >; Archive = boost::archive::binary_iarchive; Elem = char; Tr = std::char_traits<char>]’
    /usr/include/boost/archive/detail/interface_iarchive.hpp:60:9:   required from ‘Archive& boost::archive::detail::interface_iarchive<Archive>::operator>>(T&) [with T = relearn::policy<relearn::state<mumbler::state<std::__cxx11::basic_string<char> > >, relearn::action<mumbler::action<std::__cxx11::basic_string<char> > 
    > >; Archive = boost::archive::binary_iarchive]’
    /home/alex/codez/mumbler/src/agent.cpp:9:11:   required from here
    /home/alex/codez/mumbler/src/relearn/src/relearn.hpp:90:5: error: ‘relearn::state<state_trait, value_type>::state() [with state_trait = mumbler::state<std::__cxx11::basic_string<char> >; value_type = double]’ is private
         state() = default;
    

    据我所见,我有两个选择:

    1. 保留一个公共空的默认构造函数
    2. 前向声明类策略,然后成为它的朋友 - 但是这会产生这样一个问题:类的朋友需要知道它的模板参数,因此他们需要知道彼此(状态 - 动作)这就是我我想避免。
    3. 有没有其他方法可以解决这个问题而不暴露公共空构造函数?

      修改

      这不是重复,我知道如何(de)序列化,问题是隐藏默认构造函数,只有(de)序列化程序可以访问它。

1 个答案:

答案 0 :(得分:2)

创建默认构造函数protected,然后从具有公共构造函数的每个构造函数创建一个派生类,但完全从外部隐藏这些派生类(将它们放在detail头文件中,其他人不包含)。然后你的policy类可以在内部使用派生类,用于序列化和存储,但只将它们公开为(切片的)基类对象。