title: How BOOST_CLASS_EXPORT_IMPLEMENT instantiate serialize function for all used archives?
body: <p>From <a href="http://www.boost.org/doc/libs/1_55_0/libs/serialization/doc/serialization.html#instantiation" rel="nofollow">documentation</a> of boots/serialization:</p>
  
  <blockquote>
    <p>...BOOST_CLASS_EXPORT_GUID explicitly instantiates the class serialization code for all archive classes used by the program. </p>
  </blockquote>
  
  <p>I looked into the source code and found this:</p>
  
  <pre><code>#define BOOST_CLASS_EXPORT_IMPLEMENT(T)                      \
      namespace boost {                                        \
      namespace archive {                                      \
      namespace detail {                                       \
      namespace extra_detail {                                 \
      template&lt;&gt;                                               \
      struct init_guid&lt; T &gt; {                                  \
          static guid_initializer&lt; T &gt; const &amp; g;              \
      };                                                       \
      guid_initializer&lt; T &gt; const &amp; init_guid&lt; T &gt;::g =        \
          ::boost::serialization::singleton&lt;                   \
              guid_initializer&lt; T &gt;                            \
          &gt;::get_mutable_instance().export_guid();             \
      }}}}                                                     \
  /**/
  
  #define BOOST_CLASS_EXPORT_KEY2(T, K)          \
  namespace boost {                              \
  namespace serialization {                      \
  template&lt;&gt;                                     \
  struct guid_defined&lt; T &gt; : boost::mpl::true_ {}; \
  template&lt;&gt;                                     \
  inline const char * guid&lt; T &gt;(){                 \
      return K;                                  \
  }                                              \
  } /* serialization */                          \
  } /* boost */                                  \
  /**/
  
  #define BOOST_CLASS_EXPORT_GUID(T, K)                                  \
  BOOST_CLASS_EXPORT_KEY2(T, K)                                          \
  BOOST_CLASS_EXPORT_IMPLEMENT(T)                                        \
  /**/
  </code></pre>
  
  <p>I understand, how <code>BOOST_CLASS_EXPORT_KEY2</code> works - it defines template indicating that given class defines GUID and stores this string.</p>
  
  <p>But how BOOST_CLASS_EXPORT_IMPLEMENT does work? I'm reading it over and over again, but I cannot see how it <em>explicitly instantiates class serialization code for all archive classes</em>...</p>
  
  <p>I wrote following example, it works as expected, but when I debugged it, it was too complicated structure, I still don't understand.</p>
  
  <p>Example:</p>
  
  <pre><code>#include &lt;vector&gt;
  #include &lt;sstream&gt;
  #include &lt;iostream&gt;
  
  #include &lt;boost/archive/text_iarchive.hpp&gt;
  #include &lt;boost/archive/text_oarchive.hpp&gt;
  #include &lt;boost/serialization/base_object.hpp&gt;
  #include &lt;boost/serialization/export.hpp&gt;
  #include &lt;boost/serialization/serialization.hpp&gt;
  #include &lt;boost/serialization/shared_ptr.hpp&gt;
  #include &lt;boost/serialization/vector.hpp&gt;
  #include &lt;boost/smart_ptr.hpp&gt;
  
  #define UNUSED(i_param) ((void)i_param)
  
  class Base
  {
  public:
  
      Base(int i_baseValue) :
          m_baseValue(i_baseValue)
      {
  
      }
  
      virtual ~Base()
      {
  
      }
  
      virtual void print() = 0;
  
  protected:
  
      int m_baseValue;
  
  private:
  
      friend class ::boost::serialization::access;
  
      template&lt;class Archive&gt;
      void serialize(Archive &amp; ar, const unsigned int file_version)
      {
          UNUSED(file_version);
  
          ar &amp; m_baseValue;
      }
  
  };
  
  class A : public Base
  {
  public:
  
      A(int i_aValue, int i_baseValue) :
          Base(i_baseValue),
          m_aValue(i_aValue)
      {
  
      }
  
      A() :
          Base(-1),
          m_aValue(-1)
      {
  
      }
  
      ~A()
      {
  
      }
  
      void print()
      {
          ::std::cout &lt;&lt; "A, base: " &lt;&lt; m_baseValue &lt;&lt; ", a: " &lt;&lt; m_aValue &lt;&lt; ::std::endl;
      }
  
  private:
  
      friend class ::boost::serialization::access;
  
      template&lt;class Archive&gt;
      void serialize(Archive &amp; ar, const unsigned int file_version)
      {
          UNUSED(file_version);
  
          ar &amp; ::boost::serialization::base_object&lt;Base&gt;(*this);
          ar &amp; m_aValue;
      }
  
  
      int m_aValue;
  };
  
  class B : public Base
  {
  public:
  
      B(int i_bValue, int i_baseValue) :
          Base(i_baseValue),
          m_bValue(i_bValue)
      {
  
      }
  
      B() :
          Base(-2),
          m_bValue(-2)
      {
  
      }
  
      ~B()
      {
  
      }
  
      void print()
      {
          ::std::cout &lt;&lt; "B, base: " &lt;&lt; m_baseValue &lt;&lt; ", b: " &lt;&lt; m_bValue &lt;&lt; ::std::endl;
      }
  
  private:
  
      friend class ::boost::serialization::access;
  
      template&lt;class Archive&gt;
      void serialize(Archive &amp; ar, const unsigned int file_version)
      {
          UNUSED(file_version);
  
          ar &amp; ::boost::serialization::base_object&lt;Base&gt;(*this);
          ar &amp; m_bValue;
      }
  
  
      int m_bValue;
  };
  
  typedef ::boost::shared_ptr&lt;Base&gt; BasePtr;
  
  BOOST_CLASS_EXPORT_GUID(Base, "base")
  BOOST_CLASS_EXPORT_GUID(A, "A")
  BOOST_CLASS_EXPORT_GUID(B, "B")
  
  void printAll(::std::vector&lt;BasePtr&gt;&amp; data)
  {
      std::cout &lt;&lt; " --- " &lt;&lt; ::std::endl;
      for(size_t i = 0; i &lt; data.size(); ++i)
      {
          data[i]-&gt;print();
      }
      std::cout &lt;&lt; " --- " &lt;&lt; ::std::endl;
  }
  
  int main()
  {
      ::std::stringstream stream;
  
      {
          ::std::vector&lt;BasePtr&gt; data;
          data.push_back(BasePtr(new A(10, 20)));
          data.push_back(BasePtr(new B(33, 44)));
  
          printAll(data);
  
          ::boost::archive::text_oarchive ar(stream);
  
          ar &amp; data;
      }
  
      //::std::cout &lt;&lt; "Data:\n" &lt;&lt; stream.str() &lt;&lt; "\n";
  
      {
          ::std::vector&lt;BasePtr&gt; data;
  
          stream.seekg(0);
          ::boost::archive::text_iarchive ar(stream);
  
          ar &amp; data;
  
          printAll(data);
      }
  
      return 0;
  }
  </code></pre>
  
  <p>Output:</p>
  
  <pre><code> --- 
  A, base: 20, a: 10
  B, base: 44, b: 33
   --- 
   --- 
  A, base: 20, a: 10
  B, base: 44, b: 33
   --- 
  </code></pre>
  
  <p>Which works as expected.</p>
  
  <p><strong>Note:</strong> some people might ask why I want to know this. I don't think it's important, but it's because I need some serialization code, however boost is not usable for me for a few reasons. So I'm investigating whether I can modify boost to my needs (for example by implementing custom archive + some core code modifications) or whether it would be better to implement something own. For both cases, I would like to know, how it works so I could determine whether it's usable in my case or whether I could mimic this behaviour. Third reason is simply curiosity and hunger for knowledge.</p>
  
  <hr>
  
  <p><strong>Update:</strong></p>
  
  <p>After more hours of digging into this I found that it's here (from boost):</p>
  
  <pre><code>template&lt;class T&gt;
  struct guid_initializer
  {
      void export_guid(mpl::false_) const {
          // generates the statically-initialized objects whose constructors
          // register the information allowing serialization of T objects
          // through pointers to their base classes.
          instantiate_ptr_serialization((T*)0, 0, adl_tag());
      }
      void export_guid(mpl::true_) const {
      }
      guid_initializer const &amp; export_guid() const {
          BOOST_STATIC_WARNING(boost::is_polymorphic&lt; T &gt;::value);
          // note: exporting an abstract base class will have no effect
          // and cannot be used to instantitiate serialization code
          // (one might be using this in a DLL to instantiate code)
          //BOOST_STATIC_WARNING(! boost::serialization::is_abstract&lt; T &gt;::value);
          export_guid(boost::serialization::is_abstract&lt; T &gt;());
          return *this;
      }
  };
  </code></pre>
  
  <p>while registering an archive is handled here:</p>
  
  <pre><code>// This function gets called, but its only purpose is to participate
  // in overload resolution with the functions declared by
  // BOOST_SERIALIZATION_REGISTER_ARCHIVE, below.
  template &lt;class Serializable&gt;
  void instantiate_ptr_serialization(Serializable*, int, adl_tag ) {}
  
  // The function declaration generated by this macro never actually
  // gets called, but its return type gets instantiated, and that's
  // enough to cause registration of serialization functions between
  // Archive and any exported Serializable type.  See also:
  // boost/serialization/export.hpp
  # define BOOST_SERIALIZATION_REGISTER_ARCHIVE(Archive)                  \
  namespace boost { namespace archive { namespace detail {                \
                                                                          \
  template &lt;class Serializable&gt;                                           \
  BOOST_DEDUCED_TYPENAME _ptr_serialization_support&lt;Archive, Serializable&gt;::type  \
  instantiate_ptr_serialization( Serializable*, Archive*, adl_tag );              \
                                                                          \
  </code></pre>
  
  <p>however I still don't see how it works. From documentation I only understand the usage, not principle how it works. You need to register your <code>Archive</code> implementation and then exporting the derived classes will create serialization method specialization for each end every registered archive. How?</p>