<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>TiMoch &#187; templates</title>
	<atom:link href="https://timoch.com/blog/tag/templates/feed/" rel="self" type="application/rss+xml" />
	<link>https://timoch.com/blog</link>
	<description>on edge</description>
	<lastBuildDate>Tue, 29 Apr 2014 15:02:50 +0000</lastBuildDate>
	<language>en-US</language>
		<sy:updatePeriod>hourly</sy:updatePeriod>
		<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=3.9.40</generator>
	<item>
		<title>boost::serialization coupling issue</title>
		<link>https://timoch.com/blog/2013/04/boost-serialization-coupling-issue/</link>
		<comments>https://timoch.com/blog/2013/04/boost-serialization-coupling-issue/#comments</comments>
		<pubDate>Fri, 12 Apr 2013 15:00:45 +0000</pubDate>
		<dc:creator><![CDATA[timoch]]></dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[c++]]></category>
		<category><![CDATA[templates]]></category>

		<guid isPermaLink="false">http://www.timoch.com/blog/?p=159</guid>
		<description><![CDATA[I was evaluating boost::serialization today. Based on the design goals mentioned in the library&#8217;s introduction, I felt like boost::serialization would suit my needs. An interesting point is this : 8. Orthogonal specification of class serialization and archive format. That is, any file format should be able to store serialization of any arbitrary set of C++ [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>I was evaluating boost::serialization today. Based on the design goals mentioned in the library&#8217;s <a href="http://www.boost.org/doc/libs/1_53_0/libs/serialization/doc/index.html" target="_blank">introduction</a>, I felt like <span class="codecolorer me1">boost::serialization</span> would suit my needs.</p>
<p>An interesting point is this :</p>
<p><em>8. Orthogonal specification of class serialization and archive format. That is, any file format should be able to store serialization of any arbitrary set of C++ data structures without having to alter the serialization of any class.</em></p>
<p>At first, I interpreted it as an intent to decouple the serialization code (that knows about the object&#8217;s internals) and the archive format.<br />
Consider this:</p><pre class="crayon-plain-tag">struct ClassA {
    ...
    template &lt;typename Archive&gt;
    void serialize(Archive ar, unsigned int version) {
        ar &amp; member1_;
        ar &amp; member2_;
        ...
        ar &amp; membern_;
    }
    ...
}</pre><p>All is fine, ClassA does not know the specifics of type Archive. Any object implementing the Archive concept will do just fine.</p>
<p>Yet, I have a problem with this. Inline code in headers has a tendency to irritate me. It hides the structure of the classes you implement so I often use the PImpl idiom.<br />
I want to (or must in the case of PImpl) move the implementation to ClassA.cpp.<br />
But &#8230; can I ?</p>
<p>serialize() is a template method. Can I forward declare a template method ? Well, yes.</p>
<p>In ClassA.hpp :</p><pre class="crayon-plain-tag">struct ClassA {
    ...
    template &lt;typename Archive&gt;
    void serialize(Archive &amp; ar, unsigned int version);
    ...
}</pre><p>In ClassA.cpp:</p><pre class="crayon-plain-tag">template &lt;typename Archive&gt;
void serialize(Archive &amp; ar, unsigned int version) {
    ar &amp; member1_;
    ar &amp; member2_;
    ...
    ar &amp; membern_;
}</pre><p>In main.cpp, try to serialize an instance of ClassA :</p><pre class="crayon-plain-tag">#include "ClassA.hpp"
#include &lt;boost/archive/text_oarchive.hpp&gt;
#include &lt;boost/archive/text_iarchive.hpp&gt;
#include &lt;fstream&gt;

int main(int argc, char ** argv) {
  ClassA a;

  std::ofstream ofs("output.txt");
  boost::archive::text_oarchive oa(ofs);
  oa &lt;&lt; a;

  return 0;
}</pre><p>Compile and link :</p>
<div class="codecolorer-container text dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">g++ -c main.cpp -o main.o<br />
g++ -c ClassA.cpp -o ClassA.o<br />
g++ main.o -lboost_serialization -o program<br />
main.o: In function &lt;code&gt;void boost::serialization::access::serialize&amp;lt;boost::archive::text_oarchive, classa=&quot;&quot;&amp;gt;(boost::archive::text_oarchive&amp;amp;, ClassA&amp;amp;, unsigned int)':<br />
main.cpp:(.text._ZN5boost13serialization6access9serializeINS_7archive13text_oarchiveE6ClassAEEvRT_RT0_j[_ZN5boost13serialization6access9serializeINS_7archive13text_oarchiveE6ClassAEEvRT_RT0_j]+0x25): undefined reference to</div></td></tr></tbody></table></div>
<p>void ClassA::serialize&lt;boost::archive::text_oarchive&gt;(boost::archive::text_oarchive&amp;, unsigned int)&#8217;<br />
collect2: error: ld returned 1 exit status<br />
make: *** [program] Error 1</code><br />
Does this compile ? Yes. Does this link ? &#8230; No!</p>
<p>What&#8217;s the compiler trying to tell me ? Undefined reference to ClassA::serialize(&#8230;). But I defined it, no ?<br />
Well, yes and no. You wrote the code but it is a template function. So it needs to be instantiated at compile-time. When main.cpp is compiled, it sees the forward-declaration of ClassA::serialize() and assumes that the linker will find the implementation of void ClassA::serialize&lt;boost::archive::text_oarchive&gt;(boost::archive::text_oarchive&amp;, unsigned int) somewhere.<br />
But it does not because, ClassA.cpp while implementing the template function does not instantiate it. ClassA::serialize() is parsed but never compiled into actual machine code.</p>
<p>You can check for yourself. Look at the file size :</p>
<div class="codecolorer-container text dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">-rw-rw-r-- 1 timoch timoch 940 Apr 12 12:59 ClassA.o<br />
-rw-rw-r-- 1 timoch timoch 143088 Apr 12 12:59 main.o</div></td></tr></tbody></table></div>
<p>940 bytes ? That&#8217;s not a lot.</p>
<p>You can force the instantiation of ClassA::serialize() in ClassA.cpp. Add the following at the end:</p><pre class="crayon-plain-tag">#include
template void ClassA::serialize(boost::archive::text_oarchive &amp;, unsigned int);</pre><p>It works, but is it good ? Not to me.</p>
<p>I need to include a header defining the implementation of the specific format I serialize to. I also need to include text_iarchive.hpp for the loading process to work. Tomorrow, when my object needs to be serialized to another format as part as another use case, I will need to modify its implementation file to include the specifics of that other format. I will need to do this for each and every class to be serialized &#8230; not something I would enjoy.</p>
<p>&nbsp;</p>
<h4>Conclusion</h4>
<p>&nbsp;</p>
<p>Templates provide a huge flexibility. Here it is used to enable the &amp; operator to serve as both an extract and inject operator. However, it is at the expense of forcing the client application to put the saving/loading implementation in the same compile unit as the definitions of your target format. It completely voids the efforts put toward decoupling the serialized objects and the format they serialize to.</p>
<p>There are ways to achieve the same flexibility of &#8216;same operator&#8217; saving and loading while preserving decoupling with the serialization format. I will come back to that in a later post.</p>
]]></content:encoded>
			<wfw:commentRss>https://timoch.com/blog/2013/04/boost-serialization-coupling-issue/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
