Boost C++ Libraries: Ticket #3977: Compile error on make_nvp with reference data member https://svn.boost.org/trac10/ticket/3977 <p> When I save the reference data member to the xml_archive by using make_nvp, the compile error occurs. </p> <p> Attached file 'ref_direct.cpp' is an example program to reproduce problem. </p> <div class="wiki-code"><div class="code"><pre> <span class="c1">// Compile error!</span> <span class="n">ar</span> <span class="o">&lt;&lt;</span> <span class="n">boost</span><span class="o">::</span><span class="n">serialization</span><span class="o">::</span><span class="n">make_nvp</span><span class="p">(</span><span class="s">&quot;ref_&quot;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">p</span><span class="o">-&gt;</span><span class="n">ref_</span><span class="p">);</span> </pre></div></div><p> The error message is below. </p> <pre class="wiki">error: invalid initialization of non-const reference of type ‘MyInt*&amp;’ from a temporary of type ‘MyInt*' </pre><p> We can avoid this error using additional variable or using static_cast. </p> <div class="wiki-code"><div class="code"><pre> <span class="c1">// OK</span> <span class="n">MyInt</span><span class="o">*</span> <span class="n">pRef</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">p</span><span class="o">-&gt;</span><span class="n">ref_</span><span class="p">;</span> <span class="n">ar</span> <span class="o">&lt;&lt;</span> <span class="n">boost</span><span class="o">::</span><span class="n">serialization</span><span class="o">::</span><span class="n">make_nvp</span><span class="p">(</span><span class="s">&quot;ref_&quot;</span><span class="p">,</span> <span class="n">pRef</span><span class="p">);</span> </pre></div></div><div class="wiki-code"><div class="code"><pre> <span class="c1">// OK</span> <span class="n">ar</span> <span class="o">&lt;&lt;</span> <span class="n">boost</span><span class="o">::</span><span class="n">serialization</span><span class="o">::</span><span class="n">make_nvp</span><span class="p">(</span><span class="s">&quot;ref_&quot;</span><span class="p">,</span> <span class="k">static_cast</span><span class="o">&lt;</span><span class="k">const</span> <span class="n">MyInt</span> <span class="o">*</span> <span class="k">const</span> <span class="o">&amp;&gt;</span><span class="p">(</span><span class="o">&amp;</span><span class="n">p</span><span class="o">-&gt;</span><span class="n">ref_</span><span class="p">));</span> </pre></div></div><p> But I think it's not elegant. </p> <p> My idea is that introducing the new overload of make_nvp function template. </p> <div class="wiki-code"><div class="code"><pre><span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">T</span><span class="o">&gt;</span> <span class="kr">inline</span> <span class="cp">#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING</span> <span class="k">const</span> <span class="cp">#endif</span> <span class="n">nvp</span><span class="o">&lt;</span><span class="k">const</span> <span class="n">T</span><span class="o">&gt;</span> <span class="n">make_nvp</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span> <span class="n">name</span><span class="p">,</span> <span class="k">const</span> <span class="n">T</span> <span class="o">&amp;</span> <span class="n">t</span><span class="p">){</span> <span class="k">return</span> <span class="n">nvp</span><span class="o">&lt;</span><span class="k">const</span> <span class="n">T</span><span class="o">&gt;</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">t</span><span class="p">);</span> <span class="p">}</span> </pre></div></div><p> It resolves this problem. </p> <p> Please check 'nvp_const_ref.patch' (attached file). </p> <p> After apply the patch, I already did the regression test of serialization. All test is passed. </p> <p> My testing environments are g++ (Ubuntu 4.4.1-4ubuntu9) 4.4.1 and VC++ 9.0 on Windows7. </p> en-us Boost C++ Libraries /htdocs/site/boost.png https://svn.boost.org/trac10/ticket/3977 Trac 1.4.3 kondo@… Wed, 03 Mar 2010 22:38:33 GMT attachment set https://svn.boost.org/trac10/ticket/3977 https://svn.boost.org/trac10/ticket/3977 <ul> <li><strong>attachment</strong> → <span class="trac-field-new">ref_direct.cpp</span> </li> </ul> <p> an example program to reproduce problem </p> Ticket kondo@… Wed, 03 Mar 2010 22:40:21 GMT attachment set https://svn.boost.org/trac10/ticket/3977 https://svn.boost.org/trac10/ticket/3977 <ul> <li><strong>attachment</strong> → <span class="trac-field-new">nvp_const_ref.patch</span> </li> </ul> <p> patch file to resolve this problem </p> Ticket anonymous Wed, 03 Mar 2010 22:41:03 GMT component changed; owner set https://svn.boost.org/trac10/ticket/3977#comment:1 https://svn.boost.org/trac10/ticket/3977#comment:1 <ul> <li><strong>owner</strong> set to <span class="trac-author">Robert Ramey</span> </li> <li><strong>component</strong> <span class="trac-field-old">None</span> → <span class="trac-field-new">serialization</span> </li> </ul> Ticket kondo@… Wed, 03 Mar 2010 22:48:37 GMT attachment set https://svn.boost.org/trac10/ticket/3977 https://svn.boost.org/trac10/ticket/3977 <ul> <li><strong>attachment</strong> → <span class="trac-field-new">ref_direct2.cpp</span> </li> </ul> <p> replace TAB to white space version of ref_direct.cpp </p> Ticket kondo@… Wed, 03 Mar 2010 22:49:06 GMT <link>https://svn.boost.org/trac10/ticket/3977#comment:2 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/3977#comment:2</guid> <description> <p> Sorry, In ref_direct.cpp, white spaces and TABs are mixed. I replace all TABs to white spaces in ref_direct2.cpp The program meaning is not changed. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Robert Ramey</dc:creator> <pubDate>Thu, 04 Mar 2010 06:48:58 GMT</pubDate> <title>status changed; resolution set https://svn.boost.org/trac10/ticket/3977#comment:3 https://svn.boost.org/trac10/ticket/3977#comment:3 <ul> <li><strong>status</strong> <span class="trac-field-old">new</span> → <span class="trac-field-new">closed</span> </li> <li><strong>resolution</strong> → <span class="trac-field-new">invalid</span> </li> </ul> <p> this is not an error. </p> <p> It's telling you not to pass a non-const. </p> <p> try fixing it with a const_cast instead. </p> <p> Your fix will actually create an error in some instances. The test suite doesn't test this specifically. </p> Ticket kondo@… Thu, 04 Mar 2010 11:09:42 GMT status changed; resolution deleted https://svn.boost.org/trac10/ticket/3977#comment:4 https://svn.boost.org/trac10/ticket/3977#comment:4 <ul> <li><strong>status</strong> <span class="trac-field-old">closed</span> → <span class="trac-field-new">reopened</span> </li> <li><strong>resolution</strong> <span class="trac-field-deleted">invalid</span> </li> </ul> <p> Thank you for a quick answer. </p> <blockquote class="citation"> <p> It's telling you not to pass a non-const. try fixing it with a const_cast instead. </p> </blockquote> <p> You're right. </p> <p> I used the static_cast, and it works correctly. </p> <div class="wiki-code"><div class="code"><pre> <span class="n">ar</span> <span class="o">&lt;&lt;</span> <span class="n">boost</span><span class="o">::</span><span class="n">serialization</span><span class="o">::</span><span class="n">make_nvp</span><span class="p">(</span><span class="s">&quot;ref_&quot;</span><span class="p">,</span> <span class="k">static_cast</span><span class="o">&lt;</span><span class="n">MyInt</span> <span class="o">*</span> <span class="k">const</span> <span class="o">&amp;&gt;</span><span class="p">(</span><span class="o">&amp;</span><span class="n">p</span><span class="o">-&gt;</span><span class="n">ref_</span><span class="p">));</span> </pre></div></div><blockquote class="citation"> <p> Your fix will actually create an error in some instances. The test suite doesn't test this specifically. </p> </blockquote> <p> Oh, I overlooked the side effect. </p> <p> My overload matches to temporary object that shouldn't match. </p> <div class="wiki-code"><div class="code"><pre><span class="n">boost</span><span class="o">::</span><span class="n">serialization</span><span class="o">::</span><span class="n">make_nvp</span><span class="p">(</span><span class="s">&quot;MyInt&quot;</span><span class="p">,</span> <span class="n">MyInt</span><span class="p">());</span> </pre></div></div><p> I still think that I can remove the cast from the client code without a side effect. </p> <p> I improved my patch to match only object that should match.(nvp_const_ref_ptr_special.patch) </p> <p> It matches only address of object, it no longer doesn't match temporary objects. </p> <p> How do you think about it? </p> <p> Of course I carried out all tests again. </p> <p> And all of them succeeded. </p> Ticket kondo@… Thu, 04 Mar 2010 11:11:05 GMT attachment set https://svn.boost.org/trac10/ticket/3977 https://svn.boost.org/trac10/ticket/3977 <ul> <li><strong>attachment</strong> → <span class="trac-field-new">nvp_const_ref_ptr_special.patch</span> </li> </ul> <p> improved patch file </p> Ticket Robert Ramey Thu, 04 Mar 2010 19:15:33 GMT status changed; resolution set https://svn.boost.org/trac10/ticket/3977#comment:5 https://svn.boost.org/trac10/ticket/3977#comment:5 <ul> <li><strong>status</strong> <span class="trac-field-old">reopened</span> → <span class="trac-field-new">closed</span> </li> <li><strong>resolution</strong> → <span class="trac-field-new">wontfix</span> </li> </ul> <p> This looks much better. </p> <p> But I have still have concerns about it. </p> <p> The reason that we trap a attempt to serialize a non-const is described in the rationale section of the documentation. Your fix overrides that an makes it easier for a user to create an archive which will prove to be unloadable. The current situation requires that the user either change his ref to a const ref or use a const_cast - also he could suppress tracking for that type. So the current situation requires that the user react to a potentially sever problem and take some explicit action to get around it. This saves me uncountable hours of explaining to the user where his problem might be when he later tries to load a tracked item which has changed in the course of serialization. I realize that it's a pain in many cases. But I really can't spend this much time with users who have inadvertently created unloadable archives. </p> <p> Robert Ramey </p> Ticket kondo@… Mon, 08 Mar 2010 13:31:11 GMT <link>https://svn.boost.org/trac10/ticket/3977#comment:6 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/3977#comment:6</guid> <description> <p> Now, I have understood your policy. Serializing the reference data member is asymmetric. And we should write such code. But my patch helps hide the such code. </p> <p> Now, I think to prepare below cast in my code. </p> <div class="wiki-code"><div class="code"><pre><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">&gt;</span> <span class="n">T</span><span class="o">*</span> <span class="k">const</span><span class="o">&amp;</span> <span class="n">reference_serialize_cast</span><span class="p">(</span><span class="n">T</span><span class="o">*</span> <span class="k">const</span><span class="o">&amp;</span> <span class="n">t</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">t</span><span class="p">;</span> <span class="p">}</span> </pre></div></div><div class="wiki-code"><div class="code"><pre> <span class="n">ar</span> <span class="o">&lt;&lt;</span> <span class="n">boost</span><span class="o">::</span><span class="n">serialization</span><span class="o">::</span><span class="n">make_nvp</span><span class="p">(</span><span class="s">&quot;ref_&quot;</span><span class="p">,</span> <span class="n">reference_serialize_cast</span><span class="p">(</span><span class="o">&amp;</span><span class="n">p</span><span class="o">-&gt;</span><span class="n">ref_</span><span class="p">));</span> </pre></div></div><p> By the way, </p> <blockquote class="citation"> <p> The reason that we trap a attempt to serialize a non-const is described in the rationale section of the documentation </p> </blockquote> <p> means <a href="http://www.boost.org/doc/libs/1_42_0/libs/serialization/doc/rationale.html">http://www.boost.org/doc/libs/1_42_0/libs/serialization/doc/rationale.html</a> ? </p> <p> or you mean <a href="http://www.boost.org/doc/libs/1_42_0/libs/serialization/doc/serialization.html#references">http://www.boost.org/doc/libs/1_42_0/libs/serialization/doc/serialization.html#references</a> ? </p> </description> <category>Ticket</category> </item> </channel> </rss>