mirror of
https://github.com/boostorg/utility.git
synced 2025-05-09 15:04:00 +00:00
Merged from branch to trunk
[SVN r15572]
This commit is contained in:
parent
aff985a563
commit
7439073cbf
406
value_init.htm
406
value_init.htm
@ -1,255 +1,219 @@
|
|||||||
<!DOCTYPE HTML PUBLIC "-//SoftQuad Software//DTD HoTMetaL PRO 5.0::19981217::extensions to HTML 4.0//EN" "hmpro5.dtd">
|
<html>
|
||||||
|
<head>
|
||||||
|
|
||||||
<HTML>
|
<meta http-equiv="Content-Type"
|
||||||
|
content="text/html; charset=iso-8859-1">
|
||||||
|
<title>value_initialized</title>
|
||||||
|
|
||||||
<HEAD>
|
</head>
|
||||||
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
|
<body vlink="#800080" link="#0000ff" text="#000000" bgcolor="#ffffff">
|
||||||
<META NAME="Template"
|
|
||||||
CONTENT="C:\PROGRAM FILES\MICROSOFT OFFICE\OFFICE\html.dot">
|
|
||||||
<META NAME="GENERATOR" CONTENT="Microsoft FrontPage Express 2.0">
|
|
||||||
<TITLE>Header </TITLE>
|
|
||||||
</HEAD>
|
|
||||||
|
|
||||||
<BODY BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#0000FF" VLINK="#800080">
|
<h2><img src="../../c++boost.gif" width="276" height="86">
|
||||||
<H2><IMG SRC="../../c++boost.gif" WIDTH="276" HEIGHT="86">Header <<A
|
Header <<a href="../../boost/utility/value_init.hpp">boost/utility/value_init.hpp</a>>
|
||||||
HREF="../../boost/utility/aligned_storage.hpp">boost/utility/value_init.hpp</A>>
|
</h2>
|
||||||
</H2>
|
|
||||||
<H2>Contents</H2>
|
<h2>Contents</h2>
|
||||||
<DL>
|
|
||||||
<DT><A HREF="#intro">Introduction</A></DT>
|
<dl>
|
||||||
</DL>
|
<dt><a href="#intro">Rationale</a></dt>
|
||||||
<UL>
|
<dt><a href="#rationale">Introduction</a></dt>
|
||||||
<LI><A HREF="#valueinit">value-initialization</A></LI>
|
</dl>
|
||||||
<LI><A HREF="#valueinitsyn">value-initialization syntax</A></LI>
|
|
||||||
</UL>
|
<ul>
|
||||||
<DL CLASS="page-index">
|
<li><a href="#valueinit">value-initialization</a></li>
|
||||||
<DT><A HREF="#types">Types</A></DT>
|
<li><a href="#valueinitsyn">value-initialization syntax</a></li>
|
||||||
</DL>
|
|
||||||
<UL>
|
</ul>
|
||||||
<LI><A HREF="#val_init"><CODE>value_initialized<></CODE></A></LI>
|
|
||||||
</UL>
|
<dl class="page-index">
|
||||||
<HR>
|
<dt><a href="#types">Types</a></dt>
|
||||||
<H2><A NAME="into"></A>Introduction</H2>
|
</dl>
|
||||||
<P>The C++ standard document realeased by 1998 contains the definitions of
|
|
||||||
<CODE>zero-initialization</CODE> and <CODE>default-initialization</CODE>.
|
<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="into"></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
|
Informally, zero-initialization means that the object is given the initial
|
||||||
value 0 (converted to the type) and default-initialization means that POD types
|
value 0 (converted to the type) and default-initialization means that
|
||||||
are zero-initialized while class types are initialized with their corresponding
|
POD [<a href="#references">2</a>] types are zero-initialized, while class
|
||||||
default constructors. A <I>declaration</I> can contain an <I>initializer</I>,
|
types are initialized with their corresponding default constructors. A
|
||||||
which specifies the object's initial value. The initializer can be just '()',
|
<i>declaration</i> can contain an <i>initializer</i>, which specifies the
|
||||||
which determines that the object shall be default-initialized (but see below).
|
object's initial value. The initializer can be just '()', which states that
|
||||||
However, if a <I>declaration</I> has no <I>initializer</I> and it is of a
|
the object shall be default-initialized (but see below). However, if a <i>declaration</i>
|
||||||
non-const non-static POD type, the initial value is indeterminate:<CITE>(see
|
has no <i>initializer</i> and it is of a non-<code>const</code>, non-<code>static</code>
|
||||||
8.5 for the accurate definitions)</CITE></P>
|
POD type, the initial value is indeterminate:<cite>(see §8.5 for the
|
||||||
<PRE>int x ; // no initializer. x value is indeterminate.
|
accurate definitions).</cite></p>
|
||||||
std::string s ; // no initializer, s is default-constructed.
|
|
||||||
|
|
||||||
int y = int() ;
|
<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>
|
||||||
// y is initialized using copy-initialization
|
|
||||||
// but the temporary uses an empty set of parentheses as the initializer,
|
|
||||||
// so it is default-constructed.
|
|
||||||
// A default constructed POD type is zero-initialized,
|
|
||||||
// therefore, y == 0.
|
|
||||||
|
|
||||||
void foo ( std::string ) ;
|
<h3><a name="valueinit">value-initialization</a></h3>
|
||||||
foo ( std::string() ) ;
|
|
||||||
// the temporary string is default constructed
|
|
||||||
// as indicated by the initializer () </PRE>
|
|
||||||
|
|
||||||
<H3><A NAME="valueinit">value-initialization</A></H3>
|
<p>The first <a
|
||||||
<P>The first Technical Corrigendum for the C++ Standard (TC1), whose darft was
|
href="http://anubis.dkuug.dk/JTC1/SC22/WG21/docs/cwg_defects.html">Technical
|
||||||
released to the public on Nov, 2001, introduced Core Issue 178 (among many
|
Corrigendum for the C++ Standard</a> (TC1), whose draft was released to
|
||||||
other issues, of course).</P>
|
the public in November 2001, introduced <a
|
||||||
<P> That issue introduced the new concept of <CODE>value-initialization</CODE>
|
href="http://anubis.dkuug.dk/JTC1/SC22/WG21/docs/cwg_defects.html#178">Core
|
||||||
(it also fixed the wording for zero-initialization). Informally,
|
Issue 178</a> (among many other issues, of course).</p>
|
||||||
value-initialization is similar to default-initialization with the exception
|
|
||||||
that on some cases non static data members and base class sub-objects are also
|
|
||||||
value-initialized. The difference is that an object which is value-initialized
|
|
||||||
won't have (or at least it 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 released official Std document says that '()'
|
|
||||||
invokes default-initialization, not value-initialization as it is now)</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);
|
|
||||||
int x ; // indeterminate initial value.
|
|
||||||
std::string s; // default-initialized.
|
|
||||||
eat ( int() ) ; // value-initialized
|
|
||||||
eat ( std::string() ) ; // value-initialied</PRE>
|
|
||||||
|
|
||||||
<H4><A NAME="valueinitsyn">value-initialization</A> syntax</H4>
|
<p> That issue introduced the new concept of <code>value-initialization</code>
|
||||||
<P>Value initialization is specified using (). However, the empty set of
|
(it also fixed the wording for zero-initialization). Informally, value-initialization
|
||||||
parentheses is not permited by the syntax of the initializer because it is
|
is similar to default-initialization with the exception that in some cases
|
||||||
parsed as the declaration of a function taking no arguments: </P>
|
non-static data members and base class sub-objects are also value-initialized.
|
||||||
<PRE>int x() ; // declares function int(*)()
|
The difference is that an object that is value-initialized won't have
|
||||||
int y ( int() ) ; // decalares function int(*)( int(*)() )</PRE>
|
(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>Thus, the empty () must be put in some other initialization context.</P>
|
<p>In order to specify value-initialization of an object we need to use the
|
||||||
<P>One alternative is to use copy-initialization syntax:</P>
|
empty-set initializer: (). </p>
|
||||||
<PRE>int x = int() ;</PRE>
|
|
||||||
|
|
||||||
<P>This works perfectly fine for POD types. But for non-POD class types,
|
<p><i>(but recall that the current C++ Standard states that '()' invokes default-initialization,
|
||||||
copy-initialization searches for a suitable constructor, which could be, for
|
not value-initialization)</i></p>
|
||||||
instance, the copy-constructor (it also searches for a suitable conversion
|
|
||||||
sequence but this doesn't apply in our 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>
|
|
||||||
struct W
|
|
||||||
{
|
|
||||||
// value-initialization of 'data' here.
|
|
||||||
W() : data() {}
|
|
||||||
T data ;
|
|
||||||
} ;
|
|
||||||
W<int> w ;
|
|
||||||
// w.data is value-initialized for any type. </PRE>
|
|
||||||
|
|
||||||
<P>This is the solution supplied by the value_initialized<> template
|
<p>As before, a declaration with no intializer specifies default-initialization,
|
||||||
class.</P>
|
and a declaration with a non-empty initializer specifies copy (=xxx) or
|
||||||
<H2><A NAME="types"></A>Types</H2>
|
direct (xxx) initialization. </p>
|
||||||
<H2><A NAME="val_init"><CODE>template class
|
|
||||||
value_initialized<T></CODE></A></H2>
|
|
||||||
<PRE>namespace boost {
|
|
||||||
|
|
||||||
template<class T>
|
<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>
|
||||||
class value_initialized
|
|
||||||
{
|
|
||||||
public :
|
|
||||||
|
|
||||||
value_initialized() : x() {}
|
<h4><a name="valueinitsyn">value-initialization</a> syntax</h4>
|
||||||
|
|
||||||
operator T&() const { return x ; }
|
<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>
|
||||||
|
|
||||||
T& data() const { return x ; }
|
<pre>int x() ; // declares function int(*)()<br>int y ( int() ) ; // decalares function int(*)( int(*)() )</pre>
|
||||||
|
|
||||||
private :
|
<p>Thus, the empty () must be put in some other initialization context.</p>
|
||||||
|
|
||||||
<I>impll-defined</I> x ;
|
<p>One alternative is to use copy-initialization syntax:</p>
|
||||||
} ;
|
|
||||||
|
|
||||||
template<class T>
|
<pre>int x = int() ;</pre>
|
||||||
T const& get ( value_initialized<T> const& x )
|
|
||||||
{
|
|
||||||
return x.data() ;
|
|
||||||
}
|
|
||||||
template<class T>
|
|
||||||
T& get ( value_initialized<T>& x )
|
|
||||||
{
|
|
||||||
return x.data() ;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace boost
|
<p>This works perfectly fine for POD types. But for non-POD class types,
|
||||||
</PRE>
|
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>An object of this template class is a T-wrapper convertible to
|
<p>One possible generic solution is to use value-initialization of a non static
|
||||||
<CODE>'T&'</CODE> whose wrapped object (data member of type T) is
|
data member:</p>
|
||||||
<A HREF="#valueinit">value-initialized</A> upon default-initialization of this
|
|
||||||
wrapper class: </P>
|
|
||||||
<PRE>
|
|
||||||
int zero = 0 ;
|
|
||||||
value_initialized<int> x ;
|
|
||||||
assert ( x == zero ) ;
|
|
||||||
|
|
||||||
std::string def ;
|
<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>
|
||||||
value_initialized< std::string > y ;
|
|
||||||
assert ( y == def ) ;
|
|
||||||
</PRE>
|
|
||||||
|
|
||||||
<P>The purpose of this wrapper is to provide a consistent syntax for value
|
<p><code>This is the solution supplied by the value_initialized<> template
|
||||||
initialization of scalar, union and class types (POD and non-POD) since the
|
class.</code></p>
|
||||||
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
|
|
||||||
T&, the member function data(), or the non-member friend function get():
|
|
||||||
</P>
|
|
||||||
<PRE>void watch(int);
|
|
||||||
value_initialized<int> x;
|
|
||||||
|
|
||||||
watch(x) ; // operator T& used.
|
<h2><a name="types"></a>Types</h2>
|
||||||
watch(x.data());
|
|
||||||
watch( get(x) ) // friend function get() used</PRE>
|
|
||||||
|
|
||||||
<P>Both <CODE>const and non-const</CODE> objects can be wrapped. Non-constant
|
<h2><a name="val_init"><code>template class value_initialized<T></code></a></h2>
|
||||||
objects can be modified directly from within the wrapper but constant objects
|
|
||||||
cannot:</P>
|
|
||||||
<PRE>value_initialized<int> x ;
|
|
||||||
static_cast<int&>(x) = 1 ; // OK
|
|
||||||
get(x) = 1 ; // OK
|
|
||||||
|
|
||||||
value_initialized<int const> y ;
|
<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>impll-defined</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>
|
||||||
static_cast<int&>(y) = 1 ; // ERROR: cannot cast to int&
|
|
||||||
static_cast<int const&>(y) = 1 ; // ERROR: cannot modify a const value
|
|
||||||
get(y) = 1 ; // ERROR: cannot modify a const value</PRE>
|
|
||||||
|
|
||||||
<H3>warning:</H3>
|
<p>An object of this template class is a <code>T</code>-wrapper convertible
|
||||||
<BLOCKQUOTE> <P>Both the conversion operator and the data() member function are
|
to <code>'T&'</code> whose wrapped object (data member of type <code>T</code>)
|
||||||
<CODE>const</CODE> in order to allow access to the wrapped object from a
|
is <a href="#valueinit">value-initialized</a> upon default-initialization
|
||||||
constant wrapper:</P>
|
of this wrapper class: </p>
|
||||||
<PRE>void foo(int);
|
|
||||||
value_initialized<int> const x ;
|
|
||||||
foo(x);
|
|
||||||
</PRE>
|
|
||||||
|
|
||||||
<P>But notice that this conversion operator is to <CODE>T&</CODE> but it is
|
<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>
|
||||||
itself <CODE>const</CODE>. As a consequence, if T is a non-const type, you can
|
|
||||||
modify the wrapped object even from within a constant wrapper:</P>
|
|
||||||
<PRE>value_initialized<int> const x_c ;
|
|
||||||
int& xr = x_c ; // OK, conversion to int& available even though x_c is itself const.
|
|
||||||
xr = 2 ; </PRE>
|
|
||||||
|
|
||||||
<P>The reason for this obscure behaviour is that some commonly used compilers
|
<p>The purpose of this wrapper is to provide a consistent syntax for value
|
||||||
just don't accept the following valid code:</P>
|
initialization of scalar, union and class types (POD and non-POD) since
|
||||||
<PRE>
|
the correct syntax for value initialization varies (see <a
|
||||||
struct X
|
href="#valueinitsyn">value-initialization syntax</a>)</p>
|
||||||
{
|
|
||||||
operator int&() ;
|
|
||||||
operator int const&() const ;
|
|
||||||
};
|
|
||||||
X x ;
|
|
||||||
(x == 1 ) ; // ERROR HERE!</PRE>
|
|
||||||
|
|
||||||
<P>These compilers complain about ambiguity between the conversion operators.
|
<p>The wrapped object can be accessed either through the conversion operator
|
||||||
<BR>
|
<code>T&</code>, the member function <code>data()</code>, or the
|
||||||
This is strictly wrong, but the only workaround that I know about is to provide
|
non-member function <code>get()</code>: </p>
|
||||||
only one of them, which leads to the obscure behaviour just explained.</P>
|
|
||||||
</BLOCKQUOTE>
|
|
||||||
<H3>Recomended practice: the non-member non-friend get() idiom</H3>
|
|
||||||
<P>The obscure behaviour just warned about being able to modify a non-const
|
|
||||||
wrapped object from within a constant wrapper can be avoided if access to the
|
|
||||||
wrapped object is always done through the get() idiom:</P>
|
|
||||||
<PRE>value_initialized<int> x ;
|
|
||||||
get(x) = 1 ; // OK
|
|
||||||
|
|
||||||
value_initialized<int const> cx ;
|
<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>
|
||||||
get(x) = 1 ; // ERROR: Cannot modify a const object
|
|
||||||
|
|
||||||
value_initialized<int> const x_c ;
|
<p>Both <code>const</code> and non-<code>const</code> objects can be wrapped.
|
||||||
get(x_c) = 1 ; // ERROR: Cannot modify a const object
|
Mutable objects can be modified directly from within the wrapper but constant
|
||||||
|
objects cannot:</p>
|
||||||
|
|
||||||
value_initialized<int const> const cx_c ;
|
<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>
|
||||||
get(cx_c) = 1 ; // ERROR: Cannot modify a const object
|
|
||||||
</PRE>
|
|
||||||
|
|
||||||
<HR>
|
<h3>Warning:</h3>
|
||||||
<P>Revised 23 August 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:fcacciola@gosierra.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>
|
|
||||||
</BODY>
|
|
||||||
</HTML>
|
|
||||||
|
|
||||||
|
<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ö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>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user