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 <<a href="../../boost/utility/value_init.hpp">boost/utility/value_init.hpp</a>> 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 <dt><a href="#details">Details</a></dt> 21</dl> 22 23<ul> 24 <li><a href="#valueinit">value-initialization</a></li> 25 <li><a href="#valueinitsyn">value-initialization syntax</a></li> 26 <li><a href="#compiler_issues">compiler issues</a></li> 27 28</ul> 29 30<dl class="page-index"> 31 <dt><a href="#types">Types and objects</a></dt> 32</dl> 33 34<ul> 35 <li><a href="#val_init"><code>template class value_initialized<T></code></a></li> 36 <li><a href="#initialized"><code>template class initialized<T></code></a></li> 37 <li><a href="#initialized_value"><code>initialized_value</code></a></li> 38 39</ul> 40 <a href="#acknowledgements">Acknowledgements</a><br> 41 <br> 42 43<hr> 44<h2><a name="rationale"></a>Rationale</h2> 45 46<p>Constructing and initializing objects in a generic way is difficult in 47 C++. The problem is that there are several different rules that apply 48for initialization. Depending on the type, the value of a newly constructed 49 object can be zero-initialized (logically 0), default-constructed (using 50 the default constructor), or indeterminate. When writing generic code, 51this problem must be addressed. The template <code>value_initialized</code> provides 52a solution with consistent syntax for value initialization of scalar, 53union and class types. 54Moreover, <code>value_initialized</code> offers a workaround to various 55compiler issues regarding value-initialization. 56 57Furthermore, a <code>const</code> object, <code>initialized_value</code> is provided, 58to avoid repeating the type name when retrieving the value from a 59<code>value_initialized<T></code> object. 60<br> 61 </p> 62 63<h2><a name="intro"></a>Introduction</h2> 64 65<p> 66There are various ways to initialize a variable, in C++. The following 67declarations all <em>may</em> have a local variable initialized to its default 68value: 69<pre> 70 T1 var1; 71 T2 var2 = 0; 72 T3 var3 = {}; 73 T4 var4 = T4(); 74</pre> 75Unfortunately, whether or not any of those declarations correctly 76initialize the variable very much depends on its type. The first 77declaration is valid for any <a href="http://www.sgi.com/tech/stl/DefaultConstructible.html"> 78DefaultConstructible</a> type (by definition). 79However, it does not always do an initialization! 80It correctly initializes the variable when it's an instance of a 81class, and the author of the class has provided a proper default 82constructor. On the other hand, the value of <code>var1</code> is <em>indeterminate</em> when 83its type is an arithmetic type, like <code>int</code>, <code>float</code>, or <code>char</code>. 84An arithmetic variable 85is of course initialized properly by the second declaration, <code>T2 86var2 = 0</code>. But this initialization form usually won't work for a 87class type (unless the class was especially written to support being 88initialized that way). The third form, <code>T3 var3 = {}</code> 89initializes an aggregate, typically a "C-style" <code>struct</code> or a "C-style" array. 90However, the syntax is not allowed for a class that has an explicitly declared 91constructor. (But watch out for an upcoming C++ language change, 92by Bjarne Stroustrup et al [<a href="#references">1</a>]!) 93The fourth form is the most generic form of them, as it 94can be used to initialize arithmetic types, class types, aggregates, pointers, and 95other types. The declaration, <code>T4 var4 = T4()</code>, should be read 96as follows: First a temporary object is created, by <code>T4()</code>. 97This object is <a href="#valueinit">value-initialized</a>. Next the temporary 98object is copied to the named variable, <code>var4</code>. Afterwards, the temporary 99is destroyed. While the copying and the destruction are likely to 100be optimized away, C++ still requires the type <code>T4</code> to be 101<a href="CopyConstructible.html">CopyConstructible</a>. 102(So <code>T4</code> needs to be <em>both</em> DefaultConstructible <em>and</em> CopyConstructible.) 103A class may not be CopyConstructible, for example because it may have a 104private and undefined copy constructor, 105or because it may be derived from <a href="utility.htm#Class_noncopyable">boost::noncopyable</a>. 106Scott Meyers [<a href="#references">2</a>] explains why a class would be defined like that. 107</p> 108<p> 109There is another, less obvious disadvantage to the fourth form, <code>T4 var4 = T4()</code>: 110It suffers from various <a href="#compiler_issues">compiler issues</a>, causing 111a variable to be left uninitialized in some compiler specific cases. 112</p> 113<p> 114The template <a href="#val_init"><code>value_initialized</code></a> 115offers a generic way to initialize 116an object, like <code>T4 var4 = T4()</code>, but without requiring its type 117to be CopyConstructible. And it offers a workaround to those compiler issues 118regarding value-initialization as well! It allows getting an initialized 119variable of any type; it <em>only</em> requires the type to be DefaultConstructible. 120A properly <em>value-initialized</em> object of type <code>T</code> is 121constructed by the following declaration: 122<pre> 123 value_initialized<T> var; 124</pre> 125</p> 126<p> 127The template <a href="#initialized"><code>initialized</code></a> 128offers both value-initialization and direct-initialization. 129It is especially useful as a data member type, allowing the very same object 130to be either direct-initialized or value-initialized. 131</p> 132<p> 133The <code>const</code> object <a href="#initialized_value"><code>initialized_value</code></a> 134allows value-initializing a variable as follows: 135<pre> 136 T var = initialized_value ; 137</pre> 138This form of initialization is semantically equivalent to <code>T4 var4 = T4()</code>, 139but robust against the aforementioned compiler issues. 140 141</p> 142 143<h2><a name="details"></a>Details</h2> 144<p>The C++ standard [<a href="#references">3</a>] contains the definitions 145 of <code>zero-initialization</code> and <code>default-initialization</code>. 146 Informally, zero-initialization means that the object is given the initial 147 value 0 (converted to the type) and default-initialization means that 148 POD [<a href="#references">4</a>] types are zero-initialized, while non-POD class 149 types are initialized with their corresponding default constructors. A 150<i>declaration</i> can contain an <i>initializer</i>, which specifies the 151object's initial value. The initializer can be just '()', which states that 152the object shall be value-initialized (but see below). However, if a <i>declaration</i> 153 has no <i>initializer</i> and it is of a non-<code>const</code>, non-<code>static</code> 154 POD type, the initial value is indeterminate: <cite>(see §8.5, [dcl.init], for the 155 accurate definitions).</cite></p> 156 157<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> 158 159<h3><a name="valueinit">value-initialization</a></h3> 160 161<p>The first <a 162 href="http://www.open-std.org/JTC1/SC22/WG21/docs/cwg_defects.html">Technical 163 Corrigendum for the C++ Standard</a> (TC1), whose draft was released to 164 the public in November 2001, introduced <a 165 href="http://www.open-std.org/JTC1/SC22/WG21/docs/cwg_defects.html#178">Core 166 Issue 178</a> (among many other issues, of course).</p> 167 168<p> That issue introduced the new concept of <code>value-initialization</code> 169 (it also fixed the wording for zero-initialization). Informally, value-initialization 170 is similar to default-initialization with the exception that in some cases 171 non-static data members and base class sub-objects are also value-initialized. 172 The difference is that an object that is value-initialized won't have 173(or at least is less likely to have) indeterminate values for data members 174 and base class sub-objects; unlike the case of an object default constructed. 175 (see Core Issue 178 for a normative description).</p> 176 177<p>In order to specify value-initialization of an object we need to use the 178 empty-set initializer: (). </p> 179 180<p>As before, a declaration with no intializer specifies default-initialization, 181 and a declaration with a non-empty initializer specifies copy (=xxx) or 182 direct (xxx) initialization. </p> 183 184<pre>template<class T> 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-initialized</pre> 185 186<h4><a name="valueinitsyn">value-initialization</a> syntax</h4> 187 188<p>Value initialization is specified using (). However, the empty set of 189parentheses is not permitted by the syntax of initializers because it is 190parsed as the declaration of a function taking no arguments: </p> 191 192<pre>int x() ; // declares function int(*)()</pre> 193 194<p>Thus, the empty () must be put in some other initialization context.</p> 195 196<p>One alternative is to use copy-initialization syntax:</p> 197 198<pre>int x = int() ;</pre> 199 200<p>This works perfectly fine for POD types. But for non-POD class types, 201copy-initialization searches for a suitable constructor, which could be, 202for instance, the copy-constructor (it also searches for a suitable conversion 203sequence but this doesn't apply in this context). For an arbitrary unknown 204type, using this syntax may not have the value-initialization effect intended 205because we don't know if a copy from a default constructed object is exactly 206the same as a default constructed object, and the compiler is allowed (in 207some cases), but never required to, optimize the copy away.</p> 208 209<p>One possible generic solution is to use value-initialization of a non static 210data member:</p> 211 212<pre>template<class T> <br>struct W <br>{<br> // value-initialization of 'data' here.<br> W() : data() {}<br> T data ;<br>} ;<br>W<int> w ;<br>// w.data is value-initialized for any type. </pre> 213 214<p>This is the solution as it was supplied by earlier versions of the 215<code>value_initialized<T></code> template 216 class. Unfortunately this approach suffered from various compiler issues.</p> 217 218<h4><a name="compiler_issues">compiler issues</a> </h4> 219 220Various compilers haven't yet fully implemented value-initialization. 221So when an object should be <em>value-initialized</em> (according to the C++ Standard), 222it <em>may</em> in practice still be left uninitialized, because of those 223compiler issues! It's hard to make a general statement on what those issues 224are like, because they depend on the compiler you are using, its version number, 225and the type of object you would like to have value-initialized. 226All compilers we have tested so far support value-initialization for arithmetic types properly. 227However, various compilers may leave some types of <em>aggregates</em> uninitialized, when they 228should be value-initialized. Value-initialization of objects of a pointer-to-member type may also 229go wrong on various compilers. 230</p> 231<p> 232At the moment of writing, May 2010, the following reported issues regarding 233value-initialization are still there in current compiler releases: 234<ul> 235<li> 236<a href="https://connect.microsoft.com/VisualStudio/feedback/details/100744"> 237Microsoft Visual Studio Feedback ID 100744, Value-initialization in new-expression</a> 238<br>Reported by Pavel Kuznetsov (MetaCommunications Engineering), 2005 239</li><li> 240<a href="http://connect.microsoft.com/VisualStudio/feedback/details/484295"> 241Microsoft Visual Studio Feedback ID 484295, VC++ does not value-initialize members of derived classes without user-declared constructor</a> 242<br>Reported by Sylvester Hesp, 2009 243</li><li> 244<a href="https://connect.microsoft.com/VisualStudio/feedback/details/499606"> 245Microsoft Visual Studio Feedback ID 499606, Presence of copy constructor breaks member class initialization</a> 246<br>Reported by Alex Vakulenko, 2009 247</li><li> 248<a href="http://qc.embarcadero.com/wc/qcmain.aspx?d=83751"> 249Embarcadero/C++Builder Report 83751, Value-initialization: arrays should have each element value-initialized</a> 250<br>Reported by Niels Dekker (LKEB), 2010 251</li><li> 252<a href="http://qc.embarcadero.com/wc/qcmain.aspx?d=83851"> 253Embarcadero/C++Builder Report 83851, Value-initialized temporary triggers internal backend error C1798</a> 254<br>Reported by Niels Dekker, 2010 255</li><li> 256<a href="http://qc.embarcadero.com/wc/qcmain.aspx?d=84279"> 257Embarcadero/C++Builder Report 84279, Internal compiler error (F1004), value-initializing member function pointer by "new T()"</a> 258<br>Reported by Niels Dekker, 2010 259</li><li> 260Sun CR 6947016, Sun 5.10 may fail to value-initialize an object of a non-POD aggregate. 261<br>Reported to Steve Clamage by Niels Dekker, 2010 262</li><li> 263IBM's XL V10.1 and V11.1 may fail to value-initialize a temporary of a non-POD aggregate. 264<br>Reported to Michael Wong by Niels Dekker, 2010 265</li><li> 266Intel support issue 589832, Attempt to value-initialize pointer-to-member triggers internal error 267on Intel 11.1. 268<br>Reported by John Maddock, 2010 269</li> 270</ul> 271Note that all known GCC issues regarding value-initialization are 272fixed with GCC version 4.4, including 273<a href="http://gcc.gnu.org/bugzilla/show_bug.cgi?id=30111">GCC Bug 30111</a>. 274Clang also has completely implemented value-initialization, as far as we know, 275now that <a href="http://llvm.org/bugs/show_bug.cgi?id=7139">Clang Bug 7139</a> is fixed. 276</p><p> 277 278New versions of <code>value_initialized</code> 279(Boost release version 1.35 or higher) 280offer a workaround to these issues: <code>value_initialized</code> may now clear 281its internal data, prior to constructing the object that it contains. It will do 282so for those compilers that need to have such a workaround, based on the 283<a href="../config/doc/html/boost_config/boost_macro_reference.html#boost_config.boost_macro_reference.macros_that_describe_defects" 284>compiler defect macro</a> BOOST_NO_COMPLETE_VALUE_INITIALIZATION. 285</p> 286 287<h2><a name="types"></a>Types and objects</h2> 288 289<h2><a name="val_init"><code>template class value_initialized<T></code></a></h2> 290 291<pre>namespace boost {<br><br>template<class T><br>class value_initialized<br>{ 292<br> public : 293<br> value_initialized() : x() {} 294<br> operator T const &() const { return x ; } 295<br> operator T&() { return x ; } 296<br> T const &data() const { return x ; } 297<br> T& data() { return x ; } 298<br> void swap( value_initialized& ); 299<br> 300<br> private : 301<br> <i>unspecified</i> x ; 302<br>} ; 303<br> 304<br>template<class T> 305<br>T const& get ( value_initialized<T> const& x ) 306<br>{ 307<br> return x.data() ; 308<br>} 309<br> 310<br>template<class T> 311<br>T& get ( value_initialized<T>& x ) 312<br>{ 313<br> return x.data() ; 314<br>} 315<br> 316<br>template<class T> 317<br>void swap ( value_initialized<T>& lhs, value_initialized<T>& rhs ) 318<br>{ 319<br> lhs.swap(rhs) ; 320<br>} 321<br> 322<br>} // namespace boost 323<br></pre> 324 325<p>An object of this template class is a <code>T</code>-wrapper convertible 326 to <code>'T&'</code> whose wrapped object (data member of type <code>T</code>) 327 is <a href="#valueinit">value-initialized</a> upon default-initialization 328 of this wrapper class: </p> 329 330<pre>int zero = 0 ;<br>value_initialized<int> x ;<br>assert ( x == zero ) ;<br><br>std::string def ;<br>value_initialized< std::string > y ;<br>assert ( y == def ) ;<br></pre> 331 332<p>The purpose of this wrapper is to provide a consistent syntax for value 333 initialization of scalar, union and class types (POD and non-POD) since 334 the correct syntax for value initialization varies (see <a 335 href="#valueinitsyn">value-initialization syntax</a>)</p> 336 337<p>The wrapped object can be accessed either through the conversion operator 338 <code>T&</code>, the member function <code>data()</code>, or the 339non-member function <code>get()</code>: </p> 340 341<pre>void watch(int);<br>value_initialized<int> x; 342<br><br>watch(x) ; // operator T& used.<br>watch(x.data());<br>watch( get(x) ) // function get() used</pre> 343 344<p>Both <code>const</code> and non-<code>const</code> objects can be wrapped. 345 Mutable objects can be modified directly from within the wrapper but constant 346 objects cannot:</p> 347 348<p>When <code>T</code> is a <em>Swappable</em> type, <code>value_initialized<T></code> 349 is swappable as well, by calling its <code>swap</code> member function 350 as well as by calling <code>boost::swap</code>.</p> 351 352<pre>value_initialized<int> x ; <br>static_cast<int&>(x) = 1 ; // OK<br>get(x) = 1 ; // OK 353<br><br>value_initialized<int const> y ; <br>static_cast<int&>(y) = 1 ; // ERROR: cannot cast to int&<br>static_cast<int const&>(y) = 1 ; // ERROR: cannot modify a const value<br>get(y) = 1 ; // ERROR: cannot modify a const value</pre> 354 355<h3>Warning:</h3> 356 357<p>The <code>value_initialized</code> implementation of Boost version 1.40.0 and older 358allowed <i>non-const</i> access to the wrapped object, from a constant wrapper, 359both by its conversion operator and its <code>data()</code> member function. For example:</p> 360 361<pre>value_initialized<int> const x_c ;<br>int& xr = x_c ; // OK, conversion to int& available even though x_c is itself const. 362<br>xr = 2 ; </pre> 363 364<p>The reason for this obscure behavior was that some compilers 365 didn't accept the following valid code:</p> 366 367<pre>struct X<br>{<br> operator int&() ;<br> operator int const&() const ; <br>};<br>X x ;<br>(x == 1 ) ; // ERROR HERE!</pre> 368 369<p>The current version of <code>value_initialized</code> no longer has this obscure behavior. 370As compilers nowadays widely support overloading the conversion operator by having a <code>const</code> and a <code>non-const</code> version, we have decided to fix the issue accordingly. So the current version supports the idea of logical constness. 371<br> 372 </p> 373 374<h3>Recommended practice: The non-member get() idiom</h3> 375 376<p>The obscure behavior of being able to modify a non-<code>const</code> 377wrapped object from within a constant wrapper (as was supported by previous 378versions of <code>value_initialized</code>) 379can be avoided if access to 380the wrapped object is always performed with the <code>get()</code> idiom:</p> 381 382<pre>value_initialized<int> x ;<br>get(x) = 1 ; // OK<br><br>value_initialized<int const> cx ;<br>get(x) = 1 ; // ERROR: Cannot modify a const object<br><br>value_initialized<int> const x_c ;<br>get(x_c) = 1 ; // ERROR: Cannot modify a const object<br><br>value_initialized<int const> const cx_c ;<br>get(cx_c) = 1 ; // ERROR: Cannot modify a const object<br></pre> 383 384<h2><a name="initialized"><code>template class initialized<T></code></a></h2> 385 386<pre>namespace boost {<br><br>template<class T><br>class initialized<br>{ 387<br> public : 388<br> initialized() : x() {} 389<br> explicit initialized(T const & arg) : x(arg) {} 390<br> operator T const &() const; 391<br> operator T&(); 392<br> T const &data() const; 393<br> T& data(); 394<br> void swap( initialized& ); 395<br> 396<br> private : 397<br> <i>unspecified</i> x ; 398<br>} ; 399<br> 400<br>template<class T> 401<br>T const& get ( initialized<T> const& x ); 402<br> 403<br>template<class T> 404<br>T& get ( initialized<T>& x ); 405<br> 406<br>template<class T> 407<br>void swap ( initialized<T>& lhs, initialized<T>& rhs ); 408<br> 409<br>} // namespace boost 410<br></pre> 411 412The template class <code>boost::initialized<T></code> supports both value-initialization 413and direct-initialization, so its interface is a superset of the interface 414of <code>value_initialized<T></code>: Its default-constructor 415value-initializes the wrapped object just like the default-constructor of 416<code>value_initialized<T></code>, but <code>boost::initialized<T></code> 417also offers an extra <code>explicit</code> 418constructor, which direct-initializes the wrapped object by the specified value. 419<p> 420 421<code>initialized<T></code> is especially useful when the wrapped 422object must be either value-initialized or direct-initialized, depending on 423runtime conditions. For example, <code>initialized<T></code> could 424hold the value of a data member that may be value-initialized by some 425constructors, and direct-initialized by others. 426On the other hand, if it is known beforehand that the 427object must <i>always</i> be value-initialized, <code>value_initialized<T></code> 428may be preferable. And if the object must always be 429direct-initialized, none of the two wrappers really needs to be used. 430</p> 431 432 433<h2><a name="initialized_value"><code>initialized_value</code></a></h2> 434 435<pre> 436namespace boost { 437class initialized_value_t 438{ 439 public : 440 template <class T> operator T() const ; 441}; 442 443initialized_value_t const initialized_value = {} ; 444 445} // namespace boost 446</pre> 447 448<code>initialized_value</code> provides a convenient way to get 449an initialized value: its conversion operator provides an appropriate 450<em>value-initialized</em> object for any CopyConstructible type. 451 452Suppose you need to have an initialized variable of type <code>T</code>. 453You could do it as follows: 454<pre> 455 T var = T(); 456</pre> 457But as mentioned before, this form suffers from various compiler issues. 458The template <code>value_initialized</code> offers a workaround: 459<pre> 460 T var = get( value_initialized<T>() ); 461</pre> 462Unfortunately both forms repeat the type name, which 463is rather short now (<code>T</code>), but could of course be 464more like <code>Namespace::Template<Arg>::Type</code>. 465Instead, one could use <code>initialized_value</code> as follows: 466<pre> 467 T var = initialized_value ; 468</pre> 469 470<h3><a name="references">References</a></h3> 471 [1] Bjarne Stroustrup, Gabriel Dos Reis, and J. Stephen Adamczyk wrote 472 various papers, proposing to extend the support for brace-enclosed <em>initializer lists</em> 473 in the next version of C++. 474 This would allow a variable <code>var</code> of any DefaultConstructible type 475 <code>T</code> to be <em>value-initialized</em> by doing <code>T var = {}</code>. 476 The papers are listed at Bjarne's web page, 477 <a href="http://www.research.att.com/~bs/WG21.html">My C++ Standards committee papers</a> <br> 478 [2] Scott Meyers, Effective C++, Third Edition, item 6, 479 <em>Explicitly disallow the use of compiler-generated functions you do not want</em>, 480 <a href="http://www.aristeia.com/books.html">Scott Meyers: Books and CDs</a> <br> 481 [3] The C++ Standard, Second edition (2003), ISO/IEC 14882:2003 <br> 482 [4] POD stands for "Plain Old Data" 483 484<h3><a name="acknowledgements"></a>Acknowledgements</h3> 485 value_initialized was developed by Fernando Cacciola, with help and 486suggestions from David Abrahams and Darin Adler.<br> 487Special thanks to Björn Karlsson who carefully edited and completed this documentation. 488 489<p>value_initialized was reimplemented by Fernando Cacciola and Niels Dekker 490for Boost release version 1.35 (2008), offering a workaround to various compiler issues. 491 </p> 492<p><code>boost::initialized</code> was very much inspired by feedback from Edward Diener and 493 Jeffrey Hellrung. 494 </p> 495<p>initialized_value was written by Niels Dekker, and added to Boost release version 1.36 (2008). 496 </p> 497<p>Developed by <a href="mailto:fernando_cacciola@hotmail.com">Fernando Cacciola</a>, 498 the latest version of this file can be found at <a 499 href="http://www.boost.org">www.boost.org</a>. 500 </p> 501 502<hr> 503<p>Revised 30 May 2010</p> 504 505<p>© Copyright Fernando Cacciola, 2002 - 2010.</p> 506 507<p>Distributed under the Boost Software License, Version 1.0. See 508<a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a></p> 509 510 <br> 511 <br> 512 513</body> 514</html> 515