mirror of
				https://github.com/boostorg/utility.git
				synced 2025-10-31 08:21:45 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			220 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
			
		
		
	
	
			220 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
| <html>
 | ||
| <head>
 | ||
|              
 | ||
|   <meta http-equiv="Content-Type"
 | ||
|  content="text/html; charset=iso-8859-1">
 | ||
|   <title>value_initialized</title>
 | ||
|     
 | ||
| </head>
 | ||
|   <body vlink="#800080" link="#0000ff" text="#000000" bgcolor="#ffffff">
 | ||
|                    
 | ||
| <h2><img src="../../boost.png" width="276" height="86">
 | ||
|          Header <<a href="../../boost/utility/value_init.hpp">boost/utility/value_init.hpp</a>>
 | ||
|      </h2>
 | ||
|                    
 | ||
| <h2>Contents</h2>
 | ||
|                    
 | ||
| <dl>
 | ||
|   <dt><a href="#rationale">Rationale</a></dt>
 | ||
|   <dt><a href="#intro">Introduction</a></dt>
 | ||
| </dl>
 | ||
|                    
 | ||
| <ul>
 | ||
|           <li><a href="#valueinit">value-initialization</a></li>
 | ||
|           <li><a href="#valueinitsyn">value-initialization syntax</a></li>
 | ||
|                    
 | ||
| </ul>
 | ||
|                    
 | ||
| <dl class="page-index">
 | ||
|   <dt><a href="#types">Types</a></dt>
 | ||
| </dl>
 | ||
|                    
 | ||
| <ul>
 | ||
|           <li><a href="#val_init"><code>value_initialized<></code></a></li>
 | ||
|                    
 | ||
| </ul>
 | ||
|               <a href="#acknowledgements">Acknowledgements</a><br>
 | ||
|      <br>
 | ||
|          
 | ||
| <hr>          
 | ||
| <h2><a name="rationale"></a>Rationale</h2>
 | ||
|                   
 | ||
| <p>Constructing and initializing objects in a generic way is difficult in
 | ||
|     C++. The problem is that there are several different rules that apply
 | ||
| for    initialization. Depending on the type, the value of a newly constructed
 | ||
|   object  can be zero-initialized (logically 0), default-constructed (using
 | ||
|   the default constructor), or indeterminate. When writing generic code,
 | ||
| this   problem must be addressed. <code>value_initialized</code> provides
 | ||
| a solution   with consistent syntax for value   initialization of scalar,
 | ||
| union and class   types. <br>
 | ||
|   </p>
 | ||
|         
 | ||
| <h2><a name="intro"></a>Introduction</h2>
 | ||
|      
 | ||
| <p>The C++ standard [<a href="#references">1</a>] contains the definitions 
 | ||
|     of <code>zero-initialization</code> and <code>default-initialization</code>.
 | ||
|      Informally, zero-initialization means that the object is given the initial
 | ||
|      value 0 (converted to the type) and default-initialization means that
 | ||
|  POD   [<a href="#references">2</a>] types are zero-initialized, while class
 | ||
|  types   are initialized with their corresponding default constructors. A
 | ||
| <i>declaration</i>   can contain an <i>initializer</i>, which specifies the
 | ||
| object's initial value.  The initializer can be just '()', which states that
 | ||
| the object shall be default-initialized  (but see below). However, if a <i>declaration</i> 
 | ||
|   has no <i>initializer</i>  and it is of a non-<code>const</code>, non-<code>static</code> 
 | ||
|    POD type, the initial value is indeterminate:<cite>(see §8.5 for the
 | ||
|    accurate definitions).</cite></p>
 | ||
|                    
 | ||
| <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>
 | ||
|                     
 | ||
| <h3><a name="valueinit">value-initialization</a></h3>
 | ||
|                    
 | ||
| <p>The first <a
 | ||
|  href="http://anubis.dkuug.dk/JTC1/SC22/WG21/docs/cwg_defects.html">Technical 
 | ||
|   Corrigendum for the C++ Standard</a> (TC1), whose draft   was released to
 | ||
|   the public in November 2001, introduced <a
 | ||
|  href="http://anubis.dkuug.dk/JTC1/SC22/WG21/docs/cwg_defects.html#178">Core 
 | ||
|   Issue 178</a> (among   many other issues, of course).</p>
 | ||
|                    
 | ||
| <p> That issue introduced the new concept of <code>value-initialization</code>
 | ||
|      (it also fixed the wording for zero-initialization). Informally, value-initialization 
 | ||
|     is similar to default-initialization with the exception that in some cases
 | ||
|     non-static data members and base class sub-objects are also value-initialized. 
 | ||
|     The difference is that an object that is value-initialized won't have 
 | ||
| (or    at least is less likely to have) indeterminate values for data members 
 | ||
|  and   base class sub-objects; unlike the case of an object default constructed. 
 | ||
|     (see Core Issue 178 for a normative description).</p>
 | ||
|                    
 | ||
| <p>In order to specify value-initialization of an object we need to use the
 | ||
|      empty-set initializer: (). </p>
 | ||
|                    
 | ||
| <p><i>(but recall that the current C++ Standard states that '()' invokes default-initialization,
 | ||
| not value-initialization)</i></p>
 | ||
|                    
 | ||
| <p>As before, a declaration with no intializer specifies default-initialization, 
 | ||
|     and a declaration with a non-empty initializer specifies copy (=xxx) or
 | ||
|   direct  (xxx) initialization. </p>
 | ||
|                    
 | ||
| <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-initialied</pre>
 | ||
|                     
 | ||
| <h4><a name="valueinitsyn">value-initialization</a> syntax</h4>
 | ||
|                    
 | ||
| <p>Value initialization is specified using (). However, the empty set of
 | ||
| parentheses is not permitted by the syntax of initializers because it is
 | ||
| parsed as the declaration of a function taking no arguments: </p>
 | ||
|                    
 | ||
| <pre>int x() ; // declares function int(*)()<br>int y ( int() ) ; // decalares function int(*)( int(*)() )</pre>
 | ||
|                     
 | ||
| <p>Thus, the empty () must be put in some other initialization context.</p>
 | ||
|                    
 | ||
| <p>One alternative is to use copy-initialization syntax:</p>
 | ||
|                    
 | ||
| <pre>int x = int() ;</pre>
 | ||
|                     
 | ||
| <p>This works perfectly fine for POD types. But for non-POD class types,
 | ||
| copy-initialization searches for a suitable constructor, which could be,
 | ||
| for instance, the copy-constructor (it also searches for a suitable conversion
 | ||
| sequence but this doesn't apply in this context). For an arbitrary unknown
 | ||
| type, using this syntax may not have the value-initialization effect intended
 | ||
| because we don't know if a copy from a default constructed object is exactly
 | ||
| the same as a default constructed object, and the compiler is allowed (in
 | ||
| some cases), but never required to, optimize the copy away.</p>
 | ||
|                    
 | ||
| <p>One possible generic solution is to use value-initialization of a non static
 | ||
| data member:</p>
 | ||
|                    
 | ||
| <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>
 | ||
|                     
 | ||
| <p><code>This is the solution supplied by the value_initialized<> template
 | ||
|      class.</code></p>
 | ||
|                    
 | ||
| <h2><a name="types"></a>Types</h2>
 | ||
|                    
 | ||
| <h2><a name="val_init"><code>template class value_initialized<T></code></a></h2>
 | ||
|                    
 | ||
| <pre>namespace boost {<br><br>template<class T><br>class value_initialized<br>{<br>  public :<br>    value_initialized() : x() {}<br>    operator T&() const { return x ; }<br>    T& data() const { return x ; }<br><br>  private :<br>    <i>unspecified</i> x ;<br>} ;<br><br>template<class T><br>T const& get ( value_initialized<T> const& x )<br>{<br>  return x.data() ;<br>}<br><br>template<class T><br>T& get ( value_initialized<T>& x )<br>{<br>  return x.data() ;<br>}<br><br>} // namespace boost<br></pre>
 | ||
|                     
 | ||
| <p>An object of this template class is a <code>T</code>-wrapper convertible 
 | ||
|     to <code>'T&'</code> whose wrapped object (data member of type <code>T</code>) 
 | ||
|     is <a href="#valueinit">value-initialized</a> upon default-initialization 
 | ||
|     of this wrapper class: </p>
 | ||
|                    
 | ||
| <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>
 | ||
|                     
 | ||
| <p>The purpose of this wrapper is to provide a consistent syntax for value
 | ||
|      initialization of scalar, union and class types (POD and non-POD) since
 | ||
|    the  correct syntax for value initialization varies (see <a
 | ||
|  href="#valueinitsyn">value-initialization syntax</a>)</p>
 | ||
|                    
 | ||
| <p>The wrapped object can be accessed either through the conversion operator
 | ||
|      <code>T&</code>, the member function <code>data()</code>, or the
 | ||
| non-member    function <code>get()</code>:  </p>
 | ||
|                    
 | ||
| <pre>void watch(int);<br>value_initialized<int> x;<br><br>watch(x) ; // operator T& used.<br>watch(x.data());<br>watch( get(x) ) // function get() used</pre>
 | ||
|                     
 | ||
| <p>Both <code>const</code> and non-<code>const</code> objects can be wrapped. 
 | ||
|     Mutable objects can be modified directly from within the wrapper but constant
 | ||
|     objects cannot:</p>
 | ||
|                    
 | ||
| <pre>value_initialized<int> x ; <br>static_cast<int&>(x) = 1 ; // OK<br>get(x) = 1 ; // OK<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>
 | ||
|                     
 | ||
| <h3>Warning:</h3>
 | ||
|                    
 | ||
| <p>Both the conversion operator and the <code>data()</code> member function 
 | ||
|     are <code>const</code> in order to allow access to the wrapped object 
 | ||
| from    a constant wrapper:</p>
 | ||
|                    
 | ||
| <pre>void foo(int);<br>value_initialized<int> const x ;<br>foo(x);<br></pre>
 | ||
|                     
 | ||
| <p>But notice that this conversion operator is to <code>T&</code> although 
 | ||
|     it is itself <code>const</code>. As a consequence, if <code>T</code> is
 | ||
|   a  non-<code>const</code> type, you can modify the wrapped object even from
 | ||
|    within a constant wrapper:</p>
 | ||
|                    
 | ||
| <pre>value_initialized<int> const x_c ;<br>int& xr = x_c ; // OK, conversion to int& available even though x_c is itself const.<br>xr = 2 ; </pre>
 | ||
|                     
 | ||
| <p>The reason for this obscure behavior is that some commonly used compilers
 | ||
|      just don't accept the following valid code:</p>
 | ||
|                    
 | ||
| <pre>struct X<br>{<br>  operator int&() ;<br>  operator int const&() const ;   <br>};<br>X x ;<br>(x == 1 ) ; // ERROR HERE!</pre>
 | ||
|                     
 | ||
| <p>These compilers complain about ambiguity between the conversion operators. 
 | ||
|     This complaint is incorrect, but the only workaround that I know of is 
 | ||
|  to   provide only one of them, which leads to the obscure behavior just explained.<br>
 | ||
|           </p>
 | ||
|                    
 | ||
| <h3>Recommended practice: The non-member get() idiom</h3>
 | ||
|                    
 | ||
| <p>The obscure behavior of being able to modify a non-<code>const</code>
 | ||
| wrapped object from within a constant wrapper can be avoided if access to
 | ||
| the wrapped object is always performed with the <code>get()</code> idiom:</p>
 | ||
|                    
 | ||
| <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>
 | ||
|                     
 | ||
| <h3><a name="references">References</a></h3>
 | ||
|           [1] The C++ Standard, ISO/IEC 14882:98 <br>
 | ||
|           [2] Plain Old Data           
 | ||
| <h3><a name="acknowledgements"></a>Acknowledgements</h3>
 | ||
|      value_initialized was developed by Fernando Cacciola, with help and
 | ||
| suggestions from David Abrahams and Darin Adler.<br>
 | ||
| Special thanks to Bj<42>rn Karlsson who carefully edited and completed this documentation.
 | ||
| <pre> </pre>
 | ||
|                     
 | ||
| <hr>          
 | ||
| <p>Revised 19 September 2002</p>
 | ||
|                    
 | ||
| <p>© Copyright boost.org 2002. Permission to copy, use, modify, sell 
 | ||
| and distribute this document is granted provided this copyright notice  appears 
 | ||
| in all copies. This document is provided "as is" without express or implied 
 | ||
| warranty, and with no claim as to its suitability for any purpose.</p>
 | ||
|                    
 | ||
| <p>Developed by <a href="mailto:fernando_cacciola@hotmail.com">Fernando Cacciola</a>,
 | ||
|      the latest version of this file can be found at <a
 | ||
|  href="http://www.boost.org">www.boost.org</a>, and the boost discussion list
 | ||
| at <a href="http://www.yahoogroups.com/list/boost">www.yahoogroups.com/list/boost</a>.
 | ||
|      </p>
 | ||
|  <br>
 | ||
|  <br>
 | ||
|     
 | ||
| </body>
 | ||
| </html>
 |