1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197
|
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Emulation limitations</title>
<link rel="stylesheet" href="../../../doc/src/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.78.1">
<link rel="home" href="../index.html" title="The Boost C++ Libraries BoostBook Documentation Subset">
<link rel="up" href="../move.html" title="Chapter 19. Boost.Move">
<link rel="prev" href="move_algorithms.html" title="Move algorithms">
<link rel="next" href="how_the_library_works.html" title="How the library works">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../boost.png"></td>
<td align="center"><a href="../../../index.html">Home</a></td>
<td align="center"><a href="../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="move_algorithms.html"><img src="../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../move.html"><img src="../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="how_the_library_works.html"><img src="../../../doc/src/images/next.png" alt="Next"></a>
</div>
<div class="section">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="move.emulation_limitations"></a><a class="link" href="emulation_limitations.html" title="Emulation limitations">Emulation limitations</a>
</h2></div></div></div>
<div class="toc"><dl class="toc">
<dt><span class="section"><a href="emulation_limitations.html#move.emulation_limitations.emulation_limitations_base">Initializing
base classes</a></span></dt>
<dt><span class="section"><a href="emulation_limitations.html#move.emulation_limitations.template_parameters">Template
parameters for perfect forwarding</a></span></dt>
<dt><span class="section"><a href="emulation_limitations.html#move.emulation_limitations.emulation_limitations_binding">Binding
of rvalue references to lvalues</a></span></dt>
<dt><span class="section"><a href="emulation_limitations.html#move.emulation_limitations.assignment_operator">Assignment
operator in classes derived from or holding copyable and movable types</a></span></dt>
</dl></div>
<p>
Like any emulation effort, the library has some limitations users should take
in care to achieve portable and efficient code when using the library with
C++03 conformant compilers:
</p>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="move.emulation_limitations.emulation_limitations_base"></a><a class="link" href="emulation_limitations.html#move.emulation_limitations.emulation_limitations_base" title="Initializing base classes">Initializing
base classes</a>
</h3></div></div></div>
<p>
When initializing base classes in move constructors, users must cast the
reference to a base class reference before moving it. Example:
</p>
<pre class="programlisting"><span class="comment">//Portable and efficient</span>
<span class="identifier">Derived</span><span class="special">(</span><span class="identifier">BOOST_RV_REF</span><span class="special">(</span><span class="identifier">Derived</span><span class="special">)</span> <span class="identifier">x</span><span class="special">)</span> <span class="comment">// Move ctor</span>
<span class="special">:</span> <span class="identifier">Base</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">move</span><span class="special">(</span><span class="keyword">static_cast</span><span class="special"><</span><span class="identifier">Base</span><span class="special">&>(</span><span class="identifier">x</span><span class="special">))),</span>
<span class="identifier">mem_</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">move</span><span class="special">(</span><span class="identifier">x</span><span class="special">.</span><span class="identifier">mem_</span><span class="special">))</span> <span class="special">{</span> <span class="special">}</span>
</pre>
<p>
If casting is not performed the emulation will not move construct the base
class, because no conversion is available from <code class="computeroutput"><span class="identifier">BOOST_RV_REF</span><span class="special">(</span><span class="identifier">Derived</span><span class="special">)</span></code> to <code class="computeroutput"><span class="identifier">BOOST_RV_REF</span><span class="special">(</span><span class="identifier">Base</span><span class="special">)</span></code>.
Without the cast we might obtain a compilation error (for non-copyable types)
or a less-efficient move constructor (for copyable types):
</p>
<pre class="programlisting"><span class="comment">//If Derived is copyable, then Base is copy-constructed.</span>
<span class="comment">//If not, a compilation error is issued</span>
<span class="identifier">Derived</span><span class="special">(</span><span class="identifier">BOOST_RV_REF</span><span class="special">(</span><span class="identifier">Derived</span><span class="special">)</span> <span class="identifier">x</span><span class="special">)</span> <span class="comment">// Move ctor</span>
<span class="special">:</span> <span class="identifier">Base</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">move</span><span class="special">(</span><span class="identifier">x</span><span class="special">)),</span>
<span class="identifier">mem_</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">move</span><span class="special">(</span><span class="identifier">x</span><span class="special">.</span><span class="identifier">mem_</span><span class="special">))</span> <span class="special">{</span> <span class="special">}</span>
</pre>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="move.emulation_limitations.template_parameters"></a><a class="link" href="emulation_limitations.html#move.emulation_limitations.template_parameters" title="Template parameters for perfect forwarding">Template
parameters for perfect forwarding</a>
</h3></div></div></div>
<p>
The emulation can't deal with C++0x reference collapsing rules that allow
perfect forwarding:
</p>
<pre class="programlisting"><span class="comment">//C++0x</span>
<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
<span class="keyword">void</span> <span class="identifier">forward_function</span><span class="special">(</span><span class="identifier">T</span> <span class="special">&&</span><span class="identifier">t</span><span class="special">)</span>
<span class="special">{</span> <span class="identifier">inner_function</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">forward</span><span class="special"><</span><span class="identifier">T</span><span class="special">>(</span><span class="identifier">t</span><span class="special">);</span> <span class="special">}</span>
<span class="comment">//Wrong C++03 emulation</span>
<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
<span class="keyword">void</span> <span class="identifier">forward_function</span><span class="special">(</span><span class="identifier">BOOST_RV_REF</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span> <span class="identifier">t</span><span class="special">)</span>
<span class="special">{</span> <span class="identifier">inner_function</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">forward</span><span class="special"><</span><span class="identifier">T</span><span class="special">>(</span><span class="identifier">t</span><span class="special">);</span> <span class="special">}</span>
</pre>
<p>
In C++03 emulation BOOST_RV_REF doesn't catch any const rlvalues. For more
details on forwarding see <a class="link" href="construct_forwarding.html" title="Constructor Forwarding">Constructor
Forwarding</a> chapter.
</p>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="move.emulation_limitations.emulation_limitations_binding"></a><a class="link" href="emulation_limitations.html#move.emulation_limitations.emulation_limitations_binding" title="Binding of rvalue references to lvalues">Binding
of rvalue references to lvalues</a>
</h3></div></div></div>
<p>
The <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1690.html" target="_top">first
rvalue reference</a> proposal allowed the binding of rvalue references
to lvalues:
</p>
<pre class="programlisting"><span class="identifier">func</span><span class="special">(</span><span class="identifier">Type</span> <span class="special">&&</span><span class="identifier">t</span><span class="special">);</span>
<span class="comment">//....</span>
<span class="identifier">Type</span> <span class="identifier">t</span><span class="special">;</span> <span class="comment">//Allowed</span>
<span class="identifier">func</span><span class="special">(</span><span class="identifier">t</span><span class="special">)</span>
</pre>
<p>
Later, as explained in <a href="http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2008/n2812.html" target="_top"><span class="emphasis"><em>Fixing
a Safety Problem with Rvalue References</em></span></a> this behaviour
was considered dangerous and eliminated this binding so that rvalue references
adhere to the principle of type-safe overloading: <span class="emphasis"><em>Every function
must be type-safe in isolation, without regard to how it has been overloaded</em></span>
</p>
<p>
<span class="bold"><strong>Boost.Move</strong></span> can't emulate this type-safe
overloading principle for C++03 compilers:
</p>
<pre class="programlisting"><span class="comment">//Allowed by move emulation</span>
<span class="identifier">movable</span> <span class="identifier">m</span><span class="special">;</span>
<span class="identifier">BOOST_RV_REF</span><span class="special">(</span><span class="identifier">movable</span><span class="special">)</span> <span class="identifier">r</span> <span class="special">=</span> <span class="identifier">m</span><span class="special">;</span>
</pre>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="move.emulation_limitations.assignment_operator"></a><a class="link" href="emulation_limitations.html#move.emulation_limitations.assignment_operator" title="Assignment operator in classes derived from or holding copyable and movable types">Assignment
operator in classes derived from or holding copyable and movable types</a>
</h3></div></div></div>
<p>
The macro <code class="computeroutput"><a class="link" href="../BOOST_COPYABLE_AND_MOVABLE.html" title="Macro BOOST_COPYABLE_AND_MOVABLE">BOOST_COPYABLE_AND_MOVABLE</a></code>
needs to define a copy constructor for <code class="computeroutput"><span class="identifier">copyable_and_movable</span></code>
taking a non-const parameter in C++03 compilers:
</p>
<pre class="programlisting"><span class="comment">//Generated by BOOST_COPYABLE_AND_MOVABLE</span>
<span class="identifier">copyable_and_movable</span> <span class="special">&</span><span class="keyword">operator</span><span class="special">=(</span><span class="identifier">copyable_and_movable</span><span class="special">&){/**/}</span>
</pre>
<p>
Since the non-const overload of the copy constructor is generated, compiler-generated
assignment operators for classes containing <code class="computeroutput"><span class="identifier">copyable_and_movable</span></code>
will get the non-const copy constructor overload, which will surely surprise
users:
</p>
<pre class="programlisting"><span class="keyword">class</span> <span class="identifier">holder</span>
<span class="special">{</span>
<span class="identifier">copyable_and_movable</span> <span class="identifier">c</span><span class="special">;</span>
<span class="special">};</span>
<span class="keyword">void</span> <span class="identifier">func</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">holder</span><span class="special">&</span> <span class="identifier">h</span><span class="special">)</span>
<span class="special">{</span>
<span class="identifier">holder</span> <span class="identifier">copy_h</span><span class="special">(</span><span class="identifier">h</span><span class="special">);</span> <span class="comment">//<--- ERROR: can't convert 'const holder&' to 'holder&'</span>
<span class="comment">//Compiler-generated copy constructor is non-const:</span>
<span class="comment">// holder& operator(holder &)</span>
<span class="comment">//!!!</span>
<span class="special">}</span>
</pre>
<p>
This limitation forces the user to define a const version of the copy assignment,
in all classes holding copyable and movable classes which might annoying
in some cases.
</p>
<p>
An alternative is to implement a single <code class="computeroutput"><span class="keyword">operator</span>
<span class="special">=()</span></code> for copyable and movable classes
<a href="http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/" target="_top">using
"pass by value" semantics</a>:
</p>
<pre class="programlisting"><span class="identifier">T</span><span class="special">&</span> <span class="keyword">operator</span><span class="special">=(</span><span class="identifier">T</span> <span class="identifier">x</span><span class="special">)</span> <span class="comment">// x is a copy of the source; hard work already done</span>
<span class="special">{</span>
<span class="identifier">swap</span><span class="special">(*</span><span class="keyword">this</span><span class="special">,</span> <span class="identifier">x</span><span class="special">);</span> <span class="comment">// trade our resources for x's</span>
<span class="keyword">return</span> <span class="special">*</span><span class="keyword">this</span><span class="special">;</span> <span class="comment">// our (old) resources get destroyed with x</span>
<span class="special">}</span>
</pre>
<p>
However, "pass by value" is not optimal for classes (like containers,
strings, etc.) that reuse resources (like previously allocated memory) when
x is assigned from a lvalue.
</p>
</div>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright © 2008-2012 Ion Gaztanaga<p>
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
</p>
</div></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="move_algorithms.html"><img src="../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../move.html"><img src="../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="how_the_library_works.html"><img src="../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>
|