Boost C++ Libraries: Ticket #10399: Breaking change in Boost.Optional https://svn.boost.org/trac10/ticket/10399 <p> Suppose I have the following types: </p> <div class="wiki-code"><div class="code"><pre> <span class="k">struct</span> <span class="n">container</span> <span class="p">{</span> <span class="n">boost</span><span class="o">::</span><span class="n">optional</span><span class="o">&lt;</span><span class="kt">uint16_t</span><span class="o">&gt;</span> <span class="n">optional</span><span class="p">()</span> <span class="k">const</span> <span class="p">{</span> <span class="k">return</span> <span class="n">value_</span><span class="p">;</span> <span class="p">}</span> <span class="k">private</span><span class="o">:</span> <span class="n">boost</span><span class="o">::</span><span class="n">optional</span><span class="o">&lt;</span><span class="kt">uint16_t</span><span class="o">&gt;</span> <span class="n">value_</span><span class="p">;</span> <span class="p">};</span> <span class="k">struct</span> <span class="n">value_wrapper</span> <span class="p">{</span> <span class="n">value_wrapper</span><span class="p">(</span><span class="k">const</span> <span class="n">container</span><span class="o">&amp;</span> <span class="n">c</span><span class="p">)</span> <span class="o">:</span> <span class="n">c_</span><span class="p">(</span><span class="n">c</span><span class="p">)</span> <span class="p">{}</span> <span class="k">operator</span> <span class="kt">uint16_t</span> <span class="p">()</span> <span class="p">{</span> <span class="k">return</span> <span class="mi">1</span><span class="p">;</span> <span class="p">}</span> <span class="k">operator</span> <span class="n">boost</span><span class="o">::</span><span class="n">optional</span><span class="o">&lt;</span><span class="kt">uint16_t</span><span class="o">&gt;</span><span class="p">()</span> <span class="p">{</span> <span class="k">return</span> <span class="n">c_</span><span class="p">.</span><span class="n">optional</span><span class="p">();</span> <span class="p">}</span> <span class="k">private</span><span class="o">:</span> <span class="k">const</span> <span class="n">container</span><span class="o">&amp;</span> <span class="n">c_</span><span class="p">;</span> <span class="p">};</span> </pre></div></div><p> And that I have the following function: </p> <div class="wiki-code"><div class="code"><pre> <span class="n">value_wrapper</span> <span class="nf">value</span><span class="p">(</span><span class="k">const</span> <span class="n">container</span><span class="o">&amp;</span> <span class="n">c</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">value_wrapper</span><span class="p">(</span><span class="n">c</span><span class="p">);</span> <span class="p">}</span> </pre></div></div><p> The following used to work in MSVC 2010: </p> <div class="wiki-code"><div class="code"><pre> <span class="n">container</span> <span class="n">c</span><span class="p">;</span> <span class="c1">// leave c.value_ alone.</span> <span class="n">boost</span><span class="o">::</span><span class="n">optional</span><span class="o">&lt;</span><span class="kt">uint16_t</span><span class="o">&gt;</span> <span class="n">some_value</span> <span class="o">=</span> <span class="n">value</span><span class="p">(</span><span class="n">c</span><span class="p">);</span> <span class="n">assert</span><span class="p">(</span><span class="o">!</span><span class="n">some_value</span><span class="p">);</span> </pre></div></div><p> Now with Boost 1.56, this breaks because the constructor for some_value from a temporary optional is now marked explicit. </p> <p> What is the work-around for the previous behavior to be regained? All the following changes cause the assertion to fail: </p> <div class="wiki-code"><div class="code"><pre> <span class="n">boost</span><span class="o">::</span><span class="n">optional</span><span class="o">&lt;</span><span class="kt">uint16_t</span><span class="o">&gt;</span> <span class="n">some_value</span><span class="p">(</span><span class="n">value</span><span class="p">(</span><span class="n">c</span><span class="p">));</span> <span class="n">assert</span><span class="p">(</span><span class="o">!</span><span class="n">some_value</span><span class="p">);</span> <span class="c1">// some_value&#39;s constructor will use the</span> <span class="kt">uint16_t</span> <span class="n">conversion</span> <span class="k">operator</span><span class="p">,</span> <span class="n">therefore</span> <span class="n">some_value</span> <span class="o">==</span> <span class="mi">1</span> <span class="n">boost</span><span class="o">::</span><span class="n">optional</span><span class="o">&lt;</span><span class="kt">uint16_t</span><span class="o">&gt;</span> <span class="n">some_value</span> <span class="o">=</span> <span class="k">static_cast</span><span class="o">&lt;</span><span class="n">boost</span><span class="o">::</span><span class="n">optional</span><span class="o">&lt;</span><span class="kt">uint16_t</span><span class="o">&gt;</span> <span class="o">&gt;</span><span class="p">(</span><span class="n">value</span><span class="p">(</span><span class="n">c</span><span class="p">));</span> <span class="n">assert</span><span class="p">(</span><span class="o">!</span><span class="n">some_value</span><span class="p">);</span> <span class="c1">// same problem as above, </span> <span class="c1">// the temporary created will favor</span> <span class="c1">// the uint16_t conversion operator</span> </pre></div></div><p> Help? </p> <p> PS. For better context, see <a class="ext-link" href="https://github.com/cpp-netlib/cpp-netlib/blob/0.11-devel/boost/network/protocol/http/algorithms/linearize.hpp#L145"><span class="icon">​</span>https://github.com/cpp-netlib/cpp-netlib/blob/0.11-devel/boost/network/protocol/http/algorithms/linearize.hpp#L145</a> </p> en-us Boost C++ Libraries /htdocs/site/boost.png https://svn.boost.org/trac10/ticket/10399 Trac 1.4.3 Dean Michael Berris Mon, 01 Sep 2014 15:45:06 GMT <link>https://svn.boost.org/trac10/ticket/10399#comment:1 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/10399#comment:1</guid> <description> <p> Ping? Any updates on this? </p> </description> <category>Ticket</category> </item> <item> <dc:creator>akrzemi1</dc:creator> <pubDate>Tue, 20 Jan 2015 09:52:10 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/10399#comment:2 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/10399#comment:2</guid> <description> <p> This is caused by a compiler bug in MSVC, see <a class="ext-link" href="https://connect.microsoft.com/VisualStudio/feedback/details/967397/incorrect-conversion-handling-in-c"><span class="icon">​</span>https://connect.microsoft.com/VisualStudio/feedback/details/967397/incorrect-conversion-handling-in-c</a>. This was added when implementing move semantics and cannot be taken out without taking move semantics out. I could forcibly counteract Microsoft double conversions, but do not feel that this is a good idea. The problem is also observable in Boost.Variant, and no-one seams to be questioning it implementing move semantics: </p> <pre class="wiki">#include &lt;boost/variant.hpp&gt; struct Wrapper { operator int () { return 9; } operator boost::variant&lt;int, long&gt; () { return 7; } }; int main() { boost::variant&lt;int, long&gt; v = Wrapper(); assert(boost::get&lt;int&gt;(v) == 7); } </pre> </description> <category>Ticket</category> </item> <item> <dc:creator>anonymous</dc:creator> <pubDate>Wed, 18 Feb 2015 14:17:48 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/10399#comment:3 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/10399#comment:3</guid> <description> <p> It is now possible to manually disable move operations. Just define macro BOOST_OPTIONAL_CONFIG_NO_RVALUE_REFERENCES This eliminates the problem on MSVC. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>anonymous</dc:creator> <pubDate>Wed, 18 Feb 2015 14:19:55 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/10399#comment:3 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/10399#comment:3</guid> <description> <p> It is now possible to manually disable move operations. Just define macro BOOST_OPTIONAL_CONFIG_NO_RVALUE_REFERENCES This eliminates the problem on MSVC. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>akrzemi1</dc:creator> <pubDate>Mon, 23 Mar 2015 20:44:23 GMT</pubDate> <title>owner, status changed https://svn.boost.org/trac10/ticket/10399#comment:4 https://svn.boost.org/trac10/ticket/10399#comment:4 <ul> <li><strong>owner</strong> changed from <span class="trac-author">Fernando Cacciola</span> to <span class="trac-author">akrzemi1</span> </li> <li><strong>status</strong> <span class="trac-field-old">new</span> → <span class="trac-field-new">assigned</span> </li> </ul> Ticket akrzemi1 Mon, 23 Mar 2015 20:45:07 GMT status, milestone changed; resolution set https://svn.boost.org/trac10/ticket/10399#comment:5 https://svn.boost.org/trac10/ticket/10399#comment:5 <ul> <li><strong>status</strong> <span class="trac-field-old">assigned</span> → <span class="trac-field-new">closed</span> </li> <li><strong>resolution</strong> → <span class="trac-field-new">wontfix</span> </li> <li><strong>milestone</strong> <span class="trac-field-old">To Be Determined</span> → <span class="trac-field-new">Boost 1.58.0</span> </li> </ul> Ticket