Get private data members for non intrusive boost serialization C++

后端 未结 3 560
余生分开走
余生分开走 2020-12-06 03:01

I have tried providing getters of class A for my non-member serialize() function` since accessing from members is private.

template         


        
3条回答
  •  渐次进展
    2020-12-06 03:33

    1. You can use good old-fashioned friends:

      Live On Coliru

      template 
      class A {
        public:
          A(const T &id) : m_id(id) {}
        private:
          template  friend void boost::serialization::serialize(Ar&,A&,const unsigned);
          T m_id;
      };
      
      namespace boost {
      namespace serialization {
          template 
          void serialize(Archive &ar, A &a, const unsigned int)
          {
              ar & BOOST_SERIALIZATION_NVP(a.m_id);
          }
      }
      }
      

    2. You can use the getRef() approach. This

      • requires no friends (less intrusive)
      • requires make_nvp (because you can't use a.getRef() as an XML element name

      Sadly, having the reference getter break encapsulation in a horrific way. I'd personally prefer to have m_id public in the first place, instead.

      Live On Coliru

      template 
      class A {
      public:
          A(const T &id) : m_id(id) {}
      
          T& getRef()             { return m_id; } 
          T const& getRef() const { return m_id; } 
      private:
          T m_id;
      };
      
      namespace boost {
      namespace serialization {
          template 
          void serialize(Archive &ar, A &a, const unsigned int)
          {
              ar & boost::serialization::make_nvp("m_id", a.getRef());
          }
      }
      }
      

      Bonus points:

    3. You can use a 'pimpl' style struct. You can forward declare a struct inside A<>:

      template 
      class A {
      public:
          struct access;
      
          A(const T &id) : m_id(id) {}
      private:
          T m_id;
      };
      

      That's less intrusive than the getRef() approach which simply breaks encapsulation all the way. Now, you can hide the private access inside this class:

      namespace boost {
      namespace serialization {
          template 
          void serialize(Archive &ar, A &a, const unsigned int version)
          {
              A::access::serialize(ar, a, version);
          }
      }
      }
      

      Of course you still need to implement it, but this can be done in a separate header and doesn't influence class A<> (or any of its specializations) at all:

      template 
      struct A::access {
          template 
          static void serialize(Archive &ar, A &a, const unsigned int) {
              ar & BOOST_SERIALIZATION_NVP(a.m_id);
          }
      };
      

      See it Live On Coliru as well

提交回复
热议问题