Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_33_1/libs/utility/value_init.htm @ 12

Last change on this file since 12 was 12, checked in by landauf, 17 years ago

added boost

File size: 12.5 KB
RevLine 
[12]1<html>
2<head>
3             
4  <meta http-equiv="Content-Type"
5 content="text/html; charset=iso-8859-1">
6  <title>value_initialized</title>
7   
8</head>
9  <body vlink="#800080" link="#0000ff" text="#000000" bgcolor="#ffffff">
10                   
11<h2><img src="../../boost.png" width="276" height="86">
12         Header &lt;<a href="../../boost/utility/value_init.hpp">boost/utility/value_init.hpp</a>&gt;
13     </h2>
14                   
15<h2>Contents</h2>
16                   
17<dl>
18  <dt><a href="#rationale">Rationale</a></dt>
19  <dt><a href="#intro">Introduction</a></dt>
20</dl>
21                   
22<ul>
23          <li><a href="#valueinit">value-initialization</a></li>
24          <li><a href="#valueinitsyn">value-initialization syntax</a></li>
25                   
26</ul>
27                   
28<dl class="page-index">
29  <dt><a href="#types">Types</a></dt>
30</dl>
31                   
32<ul>
33          <li><a href="#val_init"><code>value_initialized&lt;&gt;</code></a></li>
34                   
35</ul>
36              <a href="#acknowledgements">Acknowledgements</a><br>
37     <br>
38         
39<hr>         
40<h2><a name="rationale"></a>Rationale</h2>
41                 
42<p>Constructing and initializing objects in a generic way is difficult in
43    C++. The problem is that there are several different rules that apply
44for    initialization. Depending on the type, the value of a newly constructed
45  object  can be zero-initialized (logically 0), default-constructed (using
46  the default constructor), or indeterminate. When writing generic code,
47this   problem must be addressed. <code>value_initialized</code> provides
48a solution   with consistent syntax for value   initialization of scalar,
49union and class   types. <br>
50  </p>
51       
52<h2><a name="intro"></a>Introduction</h2>
53     
54<p>The C++ standard [<a href="#references">1</a>] contains the definitions
55    of <code>zero-initialization</code> and <code>default-initialization</code>.
56     Informally, zero-initialization means that the object is given the initial
57     value 0 (converted to the type) and default-initialization means that
58 POD   [<a href="#references">2</a>] types are zero-initialized, while class
59 types   are initialized with their corresponding default constructors. A
60<i>declaration</i>   can contain an <i>initializer</i>, which specifies the
61object's initial value.  The initializer can be just '()', which states that
62the object shall be default-initialized  (but see below). However, if a <i>declaration</i> 
63  has no <i>initializer</i>  and it is of a non-<code>const</code>, non-<code>static</code> 
64   POD type, the initial value is indeterminate:<cite>(see &sect;8.5 for the
65   accurate definitions).</cite></p>
66                   
67<pre>int x ; // no initializer. x value is indeterminate.<br>std::string s ; // no initializer, s is default-constructed.<br><br>int y = int() ; <br>// y is initialized using copy-initialization<br>// but the temporary uses an empty set of parentheses as the initializer,<br>// so it is default-constructed.<br>// A default constructed POD type is zero-initialized,<br>// therefore, y == 0.<br><br>void foo ( std::string ) ;<br>foo ( std::string() ) ; <br>// the temporary string is default constructed <br>// as indicated by the initializer ()  </pre>
68                   
69<h3><a name="valueinit">value-initialization</a></h3>
70                   
71<p>The first <a
72 href="http://anubis.dkuug.dk/JTC1/SC22/WG21/docs/cwg_defects.html">Technical
73  Corrigendum for the C++ Standard</a> (TC1), whose draft   was released to
74  the public in November 2001, introduced <a
75 href="http://anubis.dkuug.dk/JTC1/SC22/WG21/docs/cwg_defects.html#178">Core
76  Issue 178</a> (among   many other issues, of course).</p>
77                   
78<p> That issue introduced the new concept of <code>value-initialization</code>
79     (it also fixed the wording for zero-initialization). Informally, value-initialization
80    is similar to default-initialization with the exception that in some cases
81    non-static data members and base class sub-objects are also value-initialized.
82    The difference is that an object that is value-initialized won't have
83(or    at least is less likely to have) indeterminate values for data members
84 and   base class sub-objects; unlike the case of an object default constructed.
85    (see Core Issue 178 for a normative description).</p>
86                   
87<p>In order to specify value-initialization of an object we need to use the
88     empty-set initializer: (). </p>
89                   
90<p><i>(but recall that the current C++ Standard states that '()' invokes default-initialization,
91not value-initialization)</i></p>
92                   
93<p>As before, a declaration with no intializer specifies default-initialization,
94    and a declaration with a non-empty initializer specifies copy (=xxx) or
95  direct  (xxx) initialization. </p>
96                   
97<pre>template&lt;class T&gt; void eat(T);<br>int x ; // indeterminate initial value.<br>std::string s; // default-initialized.<br>eat ( int() ) ; // value-initialized<br>eat ( std::string() ) ; // value-initialied</pre>
98                   
99<h4><a name="valueinitsyn">value-initialization</a> syntax</h4>
100                   
101<p>Value initialization is specified using (). However, the empty set of
102parentheses is not permitted by the syntax of initializers because it is
103parsed as the declaration of a function taking no arguments: </p>
104                   
105<pre>int x() ; // declares function int(*)()<br>int y ( int() ) ; // decalares function int(*)( int(*)() )</pre>
106                   
107<p>Thus, the empty () must be put in some other initialization context.</p>
108                   
109<p>One alternative is to use copy-initialization syntax:</p>
110                   
111<pre>int x = int() ;</pre>
112                   
113<p>This works perfectly fine for POD types. But for non-POD class types,
114copy-initialization searches for a suitable constructor, which could be,
115for instance, the copy-constructor (it also searches for a suitable conversion
116sequence but this doesn't apply in this context). For an arbitrary unknown
117type, using this syntax may not have the value-initialization effect intended
118because we don't know if a copy from a default constructed object is exactly
119the same as a default constructed object, and the compiler is allowed (in
120some cases), but never required to, optimize the copy away.</p>
121                   
122<p>One possible generic solution is to use value-initialization of a non static
123data member:</p>
124                   
125<pre>template&lt;class T&gt; <br>struct W <br>{<br>  // value-initialization of 'data' here.<br>  W() : data() {}<br>  T data ;<br>} ;<br>W&lt;int&gt; w ;<br>// w.data is value-initialized for any type. </pre>
126                   
127<p><code>This is the solution supplied by the value_initialized&lt;&gt; template
128     class.</code></p>
129                   
130<h2><a name="types"></a>Types</h2>
131                   
132<h2><a name="val_init"><code>template class value_initialized&lt;T&gt;</code></a></h2>
133                   
134<pre>namespace boost {<br><br>template&lt;class T&gt;<br>class value_initialized<br>{<br>  public :<br>    value_initialized() : x() {}<br>    operator T&amp;() const { return x ; }<br>    T&amp; data() const { return x ; }<br><br>  private :<br>    <i>unspecified</i> x ;<br>} ;<br><br>template&lt;class T&gt;<br>T const&amp; get ( value_initialized&lt;T&gt; const&amp; x )<br>{<br>  return x.data() ;<br>}<br><br>template&lt;class T&gt;<br>T&amp; get ( value_initialized&lt;T&gt;&amp; x )<br>{<br>  return x.data() ;<br>}<br><br>} // namespace boost<br></pre>
135                   
136<p>An object of this template class is a <code>T</code>-wrapper convertible
137    to <code>'T&amp;'</code> whose wrapped object (data member of type <code>T</code>)
138    is <a href="#valueinit">value-initialized</a> upon default-initialization
139    of this wrapper class: </p>
140                   
141<pre>int zero = 0 ;<br>value_initialized&lt;int&gt; x ;<br>assert ( x == zero ) ;<br><br>std::string def ;<br>value_initialized&lt; std::string &gt; y ;<br>assert ( y == def ) ;<br></pre>
142                   
143<p>The purpose of this wrapper is to provide a consistent syntax for value
144     initialization of scalar, union and class types (POD and non-POD) since
145   the  correct syntax for value initialization varies (see <a
146 href="#valueinitsyn">value-initialization syntax</a>)</p>
147                   
148<p>The wrapped object can be accessed either through the conversion operator
149     <code>T&amp;</code>, the member function <code>data()</code>, or the
150non-member    function <code>get()</code></p>
151                   
152<pre>void watch(int);<br>value_initialized&lt;int&gt; x;<br><br>watch(x) ; // operator T&amp; used.<br>watch(x.data());<br>watch( get(x) ) // function get() used</pre>
153                   
154<p>Both <code>const</code> and non-<code>const</code> objects can be wrapped.
155    Mutable objects can be modified directly from within the wrapper but constant
156    objects cannot:</p>
157                   
158<pre>value_initialized&lt;int&gt; x ; <br>static_cast&lt;int&amp;&gt;(x) = 1 ; // OK<br>get(x) = 1 ; // OK<br><br>value_initialized&lt;int const&gt; y ; <br>static_cast&lt;int&amp;&gt;(y) = 1 ; // ERROR: cannot cast to int&amp;<br>static_cast&lt;int const&amp;&gt;(y) = 1 ; // ERROR: cannot modify a const value<br>get(y) = 1 ; // ERROR: cannot modify a const value</pre>
159                   
160<h3>Warning:</h3>
161                   
162<p>Both the conversion operator and the <code>data()</code> member function
163    are <code>const</code> in order to allow access to the wrapped object
164from    a constant wrapper:</p>
165                   
166<pre>void foo(int);<br>value_initialized&lt;int&gt; const x ;<br>foo(x);<br></pre>
167                   
168<p>But notice that this conversion operator is to <code>T&amp;</code> although
169    it is itself <code>const</code>. As a consequence, if <code>T</code> is
170  a  non-<code>const</code> type, you can modify the wrapped object even from
171   within a constant wrapper:</p>
172                   
173<pre>value_initialized&lt;int&gt; const x_c ;<br>int&amp; xr = x_c ; // OK, conversion to int&amp; available even though x_c is itself const.<br>xr = 2 ; </pre>
174                   
175<p>The reason for this obscure behavior is that some commonly used compilers
176     just don't accept the following valid code:</p>
177                   
178<pre>struct X<br>{<br>  operator int&amp;() ;<br>  operator int const&amp;() const ;   <br>};<br>X x ;<br>(x == 1 ) ; // ERROR HERE!</pre>
179                   
180<p>These compilers complain about ambiguity between the conversion operators.
181    This complaint is incorrect, but the only workaround that I know of is
182 to   provide only one of them, which leads to the obscure behavior just explained.<br>
183          </p>
184                   
185<h3>Recommended practice: The non-member get() idiom</h3>
186                   
187<p>The obscure behavior of being able to modify a non-<code>const</code>
188wrapped object from within a constant wrapper can be avoided if access to
189the wrapped object is always performed with the <code>get()</code> idiom:</p>
190                   
191<pre>value_initialized&lt;int&gt; x ;<br>get(x) = 1 ; // OK<br><br>value_initialized&lt;int const&gt; cx ;<br>get(x) = 1 ; // ERROR: Cannot modify a const object<br><br>value_initialized&lt;int&gt; const x_c ;<br>get(x_c) = 1 ; // ERROR: Cannot modify a const object<br><br>value_initialized&lt;int const&gt; const cx_c ;<br>get(cx_c) = 1 ; // ERROR: Cannot modify a const object<br></pre>
192                   
193<h3><a name="references">References</a></h3>
194          [1] The C++ Standard, ISO/IEC 14882:98 <br>
195          [2] Plain Old Data           
196<h3><a name="acknowledgements"></a>Acknowledgements</h3>
197     value_initialized was developed by Fernando Cacciola, with help and
198suggestions from David Abrahams and Darin Adler.<br>
199Special thanks to Björn Karlsson who carefully edited and completed this documentation.
200<pre>&nbsp;</pre>
201                   
202<hr>         
203<p>Revised 19 September 2002</p>
204                   
205<p>&copy; Copyright boost.org 2002. Permission to copy, use, modify, sell
206and distribute this document is granted provided this copyright notice  appears
207in all copies. This document is provided "as is" without express or implied
208warranty, and with no claim as to its suitability for any purpose.</p>
209                   
210<p>Developed by <a href="mailto:fernando_cacciola@hotmail.com">Fernando Cacciola</a>,
211     the latest version of this file can be found at <a
212 href="http://www.boost.org">www.boost.org</a>, and the boost discussion list
213at <a href="http://www.yahoogroups.com/list/boost">www.yahoogroups.com/list/boost</a>.
214     </p>
215 <br>
216 <br>
217   
218</body>
219</html>
Note: See TracBrowser for help on using the repository browser.