<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.3.1: http://docutils.sourceforge.net/" />
<title>Clarification of Initialization of Class Objects by rvalues</title>
<meta name="author" content="David Abrahams, Gary Powell" />
<meta name="organization" content="Boost Consulting, Amazon.com" />
<meta name="date" content="February 14, 2004" />
<style type="text/css"><!--

/*
:Author: David Goodger
:Contact: goodger@users.sourceforge.net
:date: $Date: 2004/01/28 20:46:38 $
:version: $Revision: 1.36 $
:copyright: This stylesheet has been placed in the public domain.

Default cascading style sheet for the HTML output of Docutils.
*/

.first {
  margin-top: 0 }

.last {
  margin-bottom: 0 }

a.toc-backref {
  text-decoration: none ;
  color: black }

blockquote.epigraph {
  margin: 2em 5em ; }

dd {
  margin-bottom: 0.5em }

div.abstract {
  margin: 2em 5em }

div.abstract p.topic-title {
  font-weight: bold ;
  text-align: center }

div.attention, div.caution, div.danger, div.error, div.hint,
div.important, div.note, div.tip, div.warning, div.admonition {
  margin: 2em ;
  border: medium outset ;
  padding: 1em }

div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title {
  color: red ;
  font-weight: bold ;
  font-family: sans-serif }

div.hint p.admonition-title, div.important p.admonition-title,
div.note p.admonition-title, div.tip p.admonition-title,
div.admonition p.admonition-title {
  font-weight: bold ;
  font-family: sans-serif }

div.dedication {
  margin: 2em 5em ;
  text-align: center ;
  font-style: italic }

div.dedication p.topic-title {
  font-weight: bold ;
  font-style: normal }

div.figure {
  margin-left: 2em }

div.footer, div.header {
  font-size: smaller }

div.sidebar {
  margin-left: 1em ;
  border: medium outset ;
  padding: 0em 1em ;
  background-color: #ffffee ;
  width: 40% ;
  float: right ;
  clear: right }

div.sidebar p.rubric {
  font-family: sans-serif ;
  font-size: medium }

div.system-messages {
  margin: 5em }

div.system-messages h1 {
  color: red }

div.system-message {
  border: medium outset ;
  padding: 1em }

div.system-message p.system-message-title {
  color: red ;
  font-weight: bold }

div.topic {
  margin: 2em }

h1.title {
  text-align: center }

h2.subtitle {
  text-align: center }

hr {
  width: 75% }

ol.simple, ul.simple {
  margin-bottom: 1em }

ol.arabic {
  list-style: decimal }

ol.loweralpha {
  list-style: lower-alpha }

ol.upperalpha {
  list-style: upper-alpha }

ol.lowerroman {
  list-style: lower-roman }

ol.upperroman {
  list-style: upper-roman }

p.attribution {
  text-align: right ;
  margin-left: 50% }

p.caption {
  font-style: italic }

p.credits {
  font-style: italic ;
  font-size: smaller }

p.label {
  white-space: nowrap }

p.rubric {
  font-weight: bold ;
  font-size: larger ;
  color: maroon ;
  text-align: center }

p.sidebar-title {
  font-family: sans-serif ;
  font-weight: bold ;
  font-size: larger }

p.sidebar-subtitle {
  font-family: sans-serif ;
  font-weight: bold }

p.topic-title {
  font-weight: bold }

pre.address {
  margin-bottom: 0 ;
  margin-top: 0 ;
  font-family: serif ;
  font-size: 100% }

pre.line-block {
  font-family: serif ;
  font-size: 100% }

pre.literal-block, pre.doctest-block {
  margin-left: 2em ;
  margin-right: 2em ;
  background-color: #eeeeee }

span.classifier {
  font-family: sans-serif ;
  font-style: oblique }

span.classifier-delimiter {
  font-family: sans-serif ;
  font-weight: bold }

span.interpreted {
  font-family: sans-serif }

span.option {
  white-space: nowrap }

span.option-argument {
  font-style: italic }

span.pre {
  white-space: pre }

span.problematic {
  color: red }

table {
  margin-top: 0.5em ;
  margin-bottom: 0.5em }

table.citation {
  border-left: solid thin gray ;
  padding-left: 0.5ex }

table.docinfo {
  margin: 2em 4em }

table.footnote {
  border-left: solid thin black ;
  padding-left: 0.5ex }

td, th {
  padding-left: 0.5em ;
  padding-right: 0.5em ;
  vertical-align: top }

th.docinfo-name, th.field-name {
  font-weight: bold ;
  text-align: left ;
  white-space: nowrap }

h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt {
  font-size: 100% }

tt {
  background-color: #eeeeee }

ul.auto-toc {
  list-style-type: none }

--></style>
</head>
<body>
<div class="document" id="clarification-of-initialization-of-class-objects-by-rvalues">
<h1 class="title">Clarification of Initialization of Class Objects by rvalues</h1>
<table class="docinfo" frame="void" rules="none">
<col class="docinfo-name" />
<col class="docinfo-content" />
<tbody valign="top">
<tr class="field"><th class="docinfo-name">Number:</th><td class="field-body">N1610=04-0050</td>
</tr>
<tr><th class="docinfo-name">Author:</th>
<td>David Abrahams, Gary Powell</td></tr>
<tr><th class="docinfo-name">Contact:</th>
<td><a class="first reference" href="mailto:dave&#64;boost-consulting.com">dave&#64;boost-consulting.com</a>, <a class="last reference" href="mailto:powellg&#64;amazon.com">powellg&#64;amazon.com</a></td></tr>
<tr><th class="docinfo-name">Organization:</th>
<td><a class="first reference" href="http://www.boost-consulting.com">Boost Consulting</a>, <a class="last reference" href="http://www.amazon.com">Amazon.com</a></td></tr>
<tr><th class="docinfo-name">Date:</th>
<td>February 14, 2004</td></tr>
<tr class="field"><th class="docinfo-name">Project:</th><td class="field-body">Programming Language C++, Evolution Working Group</td>
</tr>
</tbody>
</table>
<div class="contents topic" id="index">
<p class="topic-title"><a name="index">Index</a></p>
<ul class="auto-toc simple">
<li><a class="reference" href="#introduction" id="id2" name="id2">1   Introduction</a></li>
<li><a class="reference" href="#implementing-move-semantics-in-c-98" id="id3" name="id3">2   Implementing Move Semantics in C++98</a><ul class="auto-toc">
<li><a class="reference" href="#the-constructors" id="id4" name="id4">2.1   The Constructors</a><ul class="auto-toc">
<li><a class="reference" href="#non-const-lvalues" id="id5" name="id5">2.1.1   Non-<tt class="literal"><span class="pre">const</span></tt> lvalues</a></li>
<li><a class="reference" href="#const-lvalues" id="id6" name="id6">2.1.2   <tt class="literal"><span class="pre">const</span></tt> lvalues</a></li>
<li><a class="reference" href="#non-const-rvalues" id="id7" name="id7">2.1.3   Non-<tt class="literal"><span class="pre">const</span></tt> rvalues</a></li>
<li><a class="reference" href="#const-rvalues" id="id8" name="id8">2.1.4   <tt class="literal"><span class="pre">const</span></tt> rvalues</a></li>
</ul>
</li>
<li><a class="reference" href="#copy-assignment-operator" id="id9" name="id9">2.2   Copy Assignment Operator</a></li>
</ul>
</li>
<li><a class="reference" href="#the-interpretation-problem" id="id10" name="id10">3   The Interpretation Problem</a></li>
<li><a class="reference" href="#example-move-cpp" id="id11" name="id11">4   Example - <tt class="literal"><span class="pre">move.cpp</span></tt></a></li>
<li><a class="reference" href="#proposed-changes" id="id12" name="id12">5   Proposed Changes</a></li>
<li><a class="reference" href="#revision-history" id="id13" name="id13">6   Revision History</a></li>
<li><a class="reference" href="#acknowledgements" id="id14" name="id14">7   Acknowledgements</a></li>
<li><a class="reference" href="#references" id="id15" name="id15">8   References</a></li>
<li><a class="reference" href="#appendix-a-mojo" id="id16" name="id16">9   Appendix A - Mojo</a></li>
</ul>
</div>
<table class="field-list" frame="void" rules="none">
<col class="field-name" />
<col class="field-body" />
<tbody valign="top">
<tr class="field"><th class="field-name">Abstract:</th><td class="field-body"><p class="first">The interpretation of one paragraph of the C++ standard, 8.5.3
paragraph 5, has the power:</p>
<ul class="simple">
<li>to make or break the language's ability to provide near-zero
abstraction penalty in important cases, via &quot;move&quot; semantics and</li>
<li>to determine whether a common transformation, from a <tt class="literal"><span class="pre">T</span></tt> to
a <tt class="literal"><span class="pre">T</span> <span class="pre">const&amp;</span></tt> argument, is truly generic.</li>
</ul>
<p class="last">This paper proposes to clarify 8.5.3/5 so that it unambiguously
allows move semantics and allows the transformation work
uniformly.</p>
</td>
</tr>
</tbody>
</table>
<div class="section" id="introduction">
<h1><a class="toc-backref" href="#id2" name="introduction">1   Introduction</a></h1>
<p>Unnecessary temporaries and the cost of copying them are a serious
impediment to writing clear, concise and efficient code in C++.
The desire to avoid temporary copies of large objects results in
users writing code like:</p>
<pre class="literal-block">
a = b;   
a += c;
</pre>
<p>where the equivalent, but more-expressive</p>
<pre class="literal-block">
a = b + c;
</pre>
<p>is intended.  In the absence of expression template heroics, the
expressive code computes the new value of <tt class="literal"><span class="pre">a</span></tt>, then <em>copies it</em>
and throws the original copy away.  Programmers have learned to
use in-place modification (<tt class="literal"><span class="pre">operator+=</span></tt>) to avoid the final
wasteful copy.</p>
<p>The language feature needed to make the expressive code efficient
is called &quot;move semantics&quot; <a class="citation-reference" href="#n1377" id="id1" name="id1">[n1377]</a>.  Move semantics relies on
being able to &quot;steal&quot; the resources held by rvalues when those
rvalues are copied.  The rvalues are about to disappear anyway, so
it makes no sense to copy their internals -- such copying can incur
a great cost as values are passed across function boundaries.  For
example, when a function returns a <tt class="literal"><span class="pre">vector&lt;T&gt;</span></tt>, every element in
the vector must be copied just before the original vector is
destroyed. Allowed return value optimizations can help in some
cases, but compilers are not always allowed to elide the copy
construction.  If the rvalue is copy-assigned into an existing
variable, an un-elidable copy is performed. When rvalues are passed
by value as function arguments, there are no allowed optimizations
that can elide a copy construction.</p>
<p>Although a core language extension as proposed in n1377 could
make &quot;movability&quot; easier and cleaner for users to implement, move
semantics can be implemented within the current language if 8.5.3
paragraph 5 is interpreted favorably.  Many implementations,
however, interpret 8.5.3/5 unfavorably.</p>
<p>While this paper will focus on move semantics, the interpretation
of 8.5.3/5 has another important effect: an unfavorable
interpretation means that the accepted optimization of passing a
parameter by <tt class="literal"><span class="pre">const&amp;</span></tt> instead of by value is not generically
applicable.</p>
</div>
<div class="section" id="implementing-move-semantics-in-c-98">
<h1><a class="toc-backref" href="#id3" name="implementing-move-semantics-in-c-98">2   Implementing Move Semantics in C++98</a></h1>
<p>To decide whether resources may be transferred away from a
constructor argument, we need to be able to distinguish whether it
is an lvalue or an rvalue.  Without a language extension as
described in n1377, it's impossible to distinguish an rvalue
argument from an lvalue argument from <em>inside</em> a constructor, so we
must do it outside, by directing rvalues and lvalues to different
overloads.</p>
<p>The example below shows an implementation of a movable class
<tt class="literal"><span class="pre">X</span></tt>.  Here we'll walk through its implementation.</p>
<div class="section" id="the-constructors">
<h2><a class="toc-backref" href="#id4" name="the-constructors">2.1   The Constructors</a></h2>
<p>Traditional copy ctors with const reference parameters</p>
<pre class="literal-block">
X(X const&amp; rhs);
</pre>
<p>will swallow all rvalues and <tt class="literal"><span class="pre">const</span></tt> lvalues, so we cannot use
one of those if we want to distinguish rvalues from lvalues.</p>
<div class="section" id="non-const-lvalues">
<h3><a class="toc-backref" href="#id5" name="non-const-lvalues">2.1.1   Non-<tt class="literal"><span class="pre">const</span></tt> lvalues</a></h3>
<p>A copy ctor with a mutable reference parameter will swallow only
non-const lvalues, so we use one of those:</p>
<pre class="literal-block">
X(X&amp; rhs);
</pre>
</div>
<div class="section" id="const-lvalues">
<h3><a class="toc-backref" href="#id6" name="const-lvalues">2.1.2   <tt class="literal"><span class="pre">const</span></tt> lvalues</a></h3>
<p>Rvalues will never bind to a <tt class="literal"><span class="pre">T&amp;</span></tt> parameter, even if <tt class="literal"><span class="pre">T</span></tt> is a
template parameter, but const lvalues will (with <tt class="literal"><span class="pre">T</span></tt> deduced as
<tt class="literal"><span class="pre">U</span> <span class="pre">const</span></tt> for some <tt class="literal"><span class="pre">U</span></tt>), so we use a templated ctor to capture
<tt class="literal"><span class="pre">const</span></tt> lvalues.  SFINAE (14.8.3) is used to ensure that the
templated ctor is only considered when <tt class="literal"><span class="pre">T</span> <span class="pre">==</span> <span class="pre">X</span></tt>:</p>
<pre class="literal-block">
template &lt;class T, class X&gt;
struct enable_if_same
{
};

template &lt;class X&gt;
struct enable_if_same&lt;X, X&gt;
{
    typedef char type;
};

struct X
{
    ...
    // const lvalue - T will be deduced as X const
    template &lt;class T&gt;
    X(T&amp; rhs, typename enable_if_same&lt;X const,T&gt;::type = 0)
</pre>
<p>[The Mojo example in the appendinx uses a different technique for
handling const lvalues.]</p>
</div>
<div class="section" id="non-const-rvalues">
<h3><a class="toc-backref" href="#id7" name="non-const-rvalues">2.1.3   Non-<tt class="literal"><span class="pre">const</span></tt> rvalues</a></h3>
<p>To handle rvalues we rely on the backdoor used by <tt class="literal"><span class="pre">auto_ptr</span></tt>,
which allows a user-defined conversion to be used in matching a
converting ctor's argument.  A conversion operator to the
nested <tt class="literal"><span class="pre">ref</span></tt> class and a ctor taking a &quot;<tt class="literal"><span class="pre">ref</span></tt>&quot; object will be
used in the case where the argument is an rvalue:</p>
<pre class="literal-block">
struct ref { ref(X*p) : p(p) {} X* p; };

operator ref()
{
    return ref(this);
}

// non-const rvalue constructor - steals resources.
X(ref rhs);
</pre>
</div>
<div class="section" id="const-rvalues">
<h3><a class="toc-backref" href="#id8" name="const-rvalues">2.1.4   <tt class="literal"><span class="pre">const</span></tt> rvalues</a></h3>
<p>Constant rvalues are should never have their resources stolen.
Since the <tt class="literal"><span class="pre">operator</span> <span class="pre">ref()</span></tt> conversion is non-<tt class="literal"><span class="pre">const</span></tt>, that can
never happen.</p>
</div>
</div>
<div class="section" id="copy-assignment-operator">
<h2><a class="toc-backref" href="#id9" name="copy-assignment-operator">2.2   Copy Assignment Operator</a></h2>
<p><tt class="literal"><span class="pre">X</span></tt>'s only copy-assignment operator takes an <tt class="literal"><span class="pre">X</span></tt> by value:</p>
<pre class="literal-block">
X&amp; operator=(X rhs);
</pre>
<p>inside <tt class="literal"><span class="pre">operator=</span></tt>, we are free to move resources out of <tt class="literal"><span class="pre">rhs</span></tt>
and into <tt class="literal"><span class="pre">*this</span></tt>: if the argument was an lvalue, it will have
been copied into <tt class="literal"><span class="pre">rhs</span></tt>.  If the argument was an rvalue, its
resources will have been moved into <tt class="literal"><span class="pre">rhs</span></tt>.  In fact, any function
that needs to steal resources from a copy of its argument, can
safely be written to accept the argument by value, and <tt class="literal"><span class="pre">rvalues</span></tt>
of movable types won't be copied.</p>
</div>
</div>
<div class="section" id="the-interpretation-problem">
<h1><a class="toc-backref" href="#id10" name="the-interpretation-problem">3   The Interpretation Problem</a></h1>
<p>8.5.3/5 says that there must be an accessible constructor that
could be used to copy any temporary bound to a const reference.  It
does not say that this accessible ctor must be a copy ctor, yet
many implementations interpret that passage as though it says there
must must be an accessible copy ctor with a <tt class="literal"><span class="pre">const&amp;</span></tt> argument.</p>
<p>Enforcement of this interpretation is usually inconsistent.  For
example, all accept:</p>
<pre class="literal-block">
X const&amp; r = X();
</pre>
<p>while some compilers reject:</p>
<pre class="literal-block">
extern sinkref(X const&amp;);
sinkref(X());  // error - no accessible copy ctor
</pre>
<p>In the example below, many compilers fail to compile test 10
because of the way 8.5.3/5 is interpreted, while at the same time,</p>
<pre class="literal-block">
typedef X const XC;
XC(X());
</pre>
<p>does compile.  In other words, it <em>is</em> possible to construct the
const temporary from the rvalue.  We think that's the proper
criterion to use in determining test 10's legailty.  8.5.3/5
doesn't demand that a &quot;copy constructor&quot; is used to copy the
temporary, only that a constructor is used &quot;to copy the temporary&quot;.</p>
<p>It appears, looking at core issues 291/391, that there may be a
need to tighten 8.5.3/5.  When the language is fixed to specify
direct (or copy initialization), it should also unambiguously allow
the enclosed test to compile.  Not only is it within the scope of
reasonable interpretation of the current standard, but it's an
incredibly important piece of functionality for users.</p>
<p>Note also that, with an unfavorable interpretation, 8.5.3/5 means
that rvalues of classes like <tt class="literal"><span class="pre">X</span></tt> (and <tt class="literal"><span class="pre">std::auto_ptr&lt;T&gt;</span></tt>)
cannot be passed where a <tt class="literal"><span class="pre">const&amp;</span></tt> parameter is expected, even
though they can be passed by value.  Move semantics aside, this
quirky non-uniformity can make writing generic code extremely
difficult.</p>
</div>
<div class="section" id="example-move-cpp">
<h1><a class="toc-backref" href="#id11" name="example-move-cpp">4   Example - <tt class="literal"><span class="pre">move.cpp</span></tt></a></h1>
<p>This example shows the implementation of a class <tt class="literal"><span class="pre">X</span></tt> supporting
move semantics.  An earlier approach by Andrei Alexandrescu is
included as an appendix.</p>
<pre class="literal-block">
// move.cpp
// Author : David Abrahams
// Uses SFINAE to get the compiler to pick the correct constructor.


#include &lt;iostream&gt;
#include &lt;cassert&gt;

template &lt;class T, class X&gt;
struct enable_if_same
{
};

template &lt;class X&gt;
struct enable_if_same&lt;X, X&gt;
{
    typedef char type;
};

struct X
{
    static int cnt;  // count the number of Xs

    X()
      : id(++cnt)
      , owner(true)
    {
        std::cout &lt;&lt; &quot;X() #&quot; &lt;&lt; id &lt;&lt; std::endl;
    }

    // non-const lvalue - copy ctor
    X(X&amp; rhs)
      : id(++cnt)
      , owner(true)
    {
        std::cout &lt;&lt; &quot;copy #&quot; &lt;&lt; id &lt;&lt; &quot; &lt;- #&quot; &lt;&lt; rhs.id &lt;&lt; std::endl;
    }

    // const lvalue - T will be deduced as X const
    template &lt;class T&gt;
    X(T&amp; rhs, typename enable_if_same&lt;X const,T&gt;::type = 0)
      : id(++cnt)
      , owner(true)
    {
        std::cout &lt;&lt; &quot;copy #&quot; &lt;&lt; id &lt;&lt; &quot; &lt;- #&quot; &lt;&lt; rhs.id &lt;&lt; &quot; (const)&quot; &lt;&lt; std::endl;
    }

    ~X()
    {
        std::cout &lt;&lt; &quot;destroy #&quot; &lt;&lt; id &lt;&lt; (owner?&quot;&quot;:&quot; (EMPTY)&quot;) &lt;&lt; std::endl;
    }

    X&amp; operator=(X rhs)
    {
        std::cout &lt;&lt; &quot;ASSIGN #&quot; &lt;&lt; id &lt;&lt; (owner?&quot;&quot;:&quot; (EMPTY)&quot;) &lt;&lt; &quot; &lt;== #&quot; &lt;&lt; rhs.id &lt;&lt; (rhs.owner?&quot;&quot;:&quot; (EMPTY)&quot;)  &lt;&lt; std::endl;
        owner = rhs.owner;
        rhs.owner = false;
        assert(owner);
    }

 private:    // Move stuff
    struct ref { ref(X*p) : p(p) {} X* p; };

 public:    // Move stuff
    operator ref() {
        return ref(this);
    }

    // non-const rvalue
    X(ref rhs)
      : id(++cnt)
      , owner(rhs.p-&gt;owner)
    {
        std::cout &lt;&lt; &quot;MOVE #&quot; &lt;&lt; id &lt;&lt; &quot; &lt;== #&quot; &lt;&lt; rhs.p-&gt;id &lt;&lt; std::endl;
        rhs.p-&gt;owner = false;
        assert(owner);
    }

 private:   // Data members
    int id;
    bool owner;
};

int X::cnt;


X source()
{
    return X();
}

X const csource()
{
    return X();
}

void sink(X)
{
    std::cout &lt;&lt; &quot;in rvalue sink&quot; &lt;&lt; std::endl;
}

void sink2(X&amp;)
{
    std::cout &lt;&lt; &quot;in non-const lvalue sink2&quot; &lt;&lt; std::endl;
}

void sink2(X const&amp;)
{
    std::cout &lt;&lt; &quot;in const lvalue sink2&quot; &lt;&lt; std::endl;
}

void sink3(X&amp;)
{
    std::cout &lt;&lt; &quot;in non-const lvalue sink3&quot; &lt;&lt; std::endl;
}

template &lt;class T&gt;
void tsink(T)
{
    std::cout &lt;&lt; &quot;in templated rvalue sink&quot; &lt;&lt; std::endl;
}

int main()
{
    std::cout &lt;&lt; &quot; ------ test 1, direct init from rvalue ------- &quot; &lt;&lt; std::endl;
#ifdef __GNUC__ // GCC having trouble parsing the extra parens
    X z2((0, X() ));
#else
    X z2((X()));
#endif 

    std::cout &lt;&lt; &quot; ------ test 2, copy init from rvalue ------- &quot; &lt;&lt; std::endl;
    X z4 = X();

    std::cout &lt;&lt; &quot; ------ test 3, copy init from lvalue ------- &quot; &lt;&lt; std::endl;
    X z5 = z4;

    std::cout &lt;&lt; &quot; ------ test 4, direct init from lvalue ------- &quot; &lt;&lt; std::endl;
    X z6(z4);

    std::cout &lt;&lt; &quot; ------ test 5, construct const ------- &quot; &lt;&lt; std::endl;
    X const z7;

    std::cout &lt;&lt; &quot; ------ test 6, copy init from lvalue ------- &quot; &lt;&lt; std::endl;
    X z8 = z7;

    std::cout &lt;&lt; &quot; ------ test 7, direct init from lvalue ------- &quot; &lt;&lt; std::endl;
    X z9(z7);

    std::cout &lt;&lt; &quot; ------ test 8, pass rvalue by-value ------- &quot; &lt;&lt; std::endl;
    sink(source());

    std::cout &lt;&lt; &quot; ------ test 9, pass const rvalue by-value ------- &quot; &lt;&lt; std::endl;
    sink(csource());

    std::cout &lt;&lt; &quot; ------ test 10, pass rvalue by overloaded reference ------- &quot; &lt;&lt; std::endl;
    // This one fails in Comeau's strict mode due to 8.5.3/5.  GCC 3.3.1 passes it.
    sink2(source());

    std::cout &lt;&lt; &quot; ------ test 11, pass const rvalue by overloaded reference ------- &quot; &lt;&lt; std::endl;
    sink2(csource());

#if 0    // These two correctly fail to compile, just as desired
    std::cout &lt;&lt; &quot; ------ test 12, pass rvalue by non-const reference ------- &quot; &lt;&lt; std::endl;
    sink3(source());

    std::cout &lt;&lt; &quot; ------ test 13, pass const rvalue by non-const reference ------- &quot; &lt;&lt; std::endl;
    sink3(csource());
#endif 

    std::cout &lt;&lt; &quot; ------ test 14, pass lvalue by-value ------- &quot; &lt;&lt; std::endl;
    sink(z5);

    std::cout &lt;&lt; &quot; ------ test 15, pass const lvalue by-value ------- &quot; &lt;&lt; std::endl;
    sink(z7);

    std::cout &lt;&lt; &quot; ------ test 16, pass lvalue by-reference ------- &quot; &lt;&lt; std::endl;
    sink2(z4);

    std::cout &lt;&lt; &quot; ------ test 17, pass const lvalue by const reference ------- &quot; &lt;&lt; std::endl;
    sink2(z7);

    std::cout &lt;&lt; &quot; ------ test 18, pass const lvalue by-reference ------- &quot; &lt;&lt; std::endl;
#if 0   // correctly fails to compile, just as desired
    sink3(z7);
#endif 

    std::cout &lt;&lt; &quot; ------ test 19, pass rvalue by value to template param ------- &quot; &lt;&lt; std::endl;
    tsink(source());

    std::cout &lt;&lt; &quot; ------ test 20, direct initialize a const A with an A ------- &quot; &lt;&lt; std::endl;
    typedef X const XC;
    sink2(XC(X()));

    std::cout &lt;&lt; &quot; ------ test 21, assign from lvalue ------- &quot; &lt;&lt; std::endl;
    z4 = z5;

    std::cout &lt;&lt; &quot; ------ test 22, assign from rvalue ------- &quot; &lt;&lt; std::endl;
    z4 = source();
}
</pre>
</div>
<div class="section" id="proposed-changes">
<h1><a class="toc-backref" href="#id12" name="proposed-changes">5   Proposed Changes</a></h1>
<p>We believe that, strictly speaking, no extensions to C++98 are
needed but that a general clarification of 8.5.3/5
would be helpful.</p>
<p>Suggested change to 8.5.3/5 is from:</p>
<blockquote>
-- A temporary of type &quot;cv1 T2&quot; [sic] is created, and a
constructor is called to copy the entire rvalue object into the
temporary. The reference is bound to the temporary or to a
sub-object within the temporary. 93) 
The constructor that would be
used to make the copy shall be callable whether or not the copy is
actually done.</blockquote>
<p>To:</p>
<blockquote>
-- A temporary of type &quot;cv/T2&quot;[sic] is created via direct
initialization from the entire rvalue object. The reference is
bound to the temporary or to a sub-object within the temporary. 93)
The functions that would be used in the initialization shall be
callable whether or not the temporary is actually created.</blockquote>
</div>
<div class="section" id="revision-history">
<h1><a class="toc-backref" href="#id13" name="revision-history">6   Revision History</a></h1>
<p>N1610=04-0050 is the first version.</p>
</div>
<div class="section" id="acknowledgements">
<h1><a class="toc-backref" href="#id14" name="acknowledgements">7   Acknowledgements</a></h1>
<p>Discussions among David Abrahams, Andrei Alexandrescu, and Evgeny
Karpov has renewed the interest to have either the std text
modified or clarified so that all C++03 implementations are
consistent with their treatment of initialization of classes from
rvalues.</p>
</div>
<div class="section" id="references">
<h1><a class="toc-backref" href="#id15" name="references">8   References</a></h1>
<table class="citation" frame="void" id="n1377" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<col />
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#id1" name="n1377">[n1377]</a></td><td>A Proposal to Add Move Semantics Support to the C++
September 10, 2002
<a class="reference" href="http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/papers/2002/n1377.htm">http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/papers/2002/n1377.htm</a>
Howard E. Hinnant, <a class="reference" href="mailto:hinnant&#64;twcny.rr.com">hinnant&#64;twcny.rr.com</a> , Peter Dimov,
<a class="reference" href="mailto:pdimov&#64;mmltd.net">pdimov&#64;mmltd.net</a>, Dave Abrahams , <a class="reference" href="mailto:dave&#64;boost-consulting.com">dave&#64;boost-consulting.com</a></td></tr>
</tbody>
</table>
<table class="citation" frame="void" id="mojo" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<col />
<tbody valign="top">
<tr><td class="label"><a name="mojo">[Mojo]</a></td><td>Andrei Alexandrescu, Mojo C/C++ User’s Journal, February 2003,</td></tr>
</tbody>
</table>
</div>
<div class="section" id="appendix-a-mojo">
<h1><a class="toc-backref" href="#id16" name="appendix-a-mojo">9   Appendix A - Mojo</a></h1>
<pre class="literal-block">
// Mojo uses a unique type to get the compiler to pick the right constructor.
//////////////////////////////////////////////////////////////////////////////
// MOJO: Moving Joint Objects
// Created by Andrei Alexandrescu
//
// Permission to use, copy, modify, distribute and sell this software for any 
//     purpose is hereby granted without fee, provided that the above copyright 
//     notice appear in all copies and that both that copyright notice and this 
//     permission notice appear in supporting documentation.
// The author makes no representations about the suitability of this software 
//     for any purpose. It is provided &quot;as is&quot; 
//     without express or implied warranty.
//
// Change Log:
//      28 Oct 2002 Gary Powell added operator-&gt; to constant and temporary and
//                              fnresult. Also templated conversion operators to
//                              mojo::enabled.
////////////////////////////////////////////////////////////////////////////////

#ifndef MOJO_H_
#define MOJO_H_

namespace mojo
{
    template &lt;class T&gt;
    class constant // type sugar for constants
    {
    public:
        const T* data_;

        explicit constant(const T&amp; obj) : data_(&amp;obj)
        {}

        template&lt;class S&gt;
        constant(constant&lt;S&gt; const &amp;rhs)
            : data_(rhs.data_)
        {}

        const T&amp; get() const
        {
            return *data_;
        }

        T const *operator-&gt;() const {
            return data_;
        }
    private:
        constant &amp;operator=(constant const&amp;);
    };

    // forward declaration.
    template&lt;class T&gt; class fnresult;

    template &lt;class T&gt;
    class temporary : private constant&lt;T&gt; // type sugar for temporaries
    {
        template&lt;class S&gt; friend class temporary;

    public:
        explicit temporary(T&amp; obj) 
        : constant&lt;T&gt;(obj)
        {}

        template&lt;class S&gt;
        temporary(temporary&lt;S&gt; &amp;rhs)
            : constant&lt;T&gt;(rhs)
        {}

        template&lt;class S&gt;
        temporary(fnresult&lt;S&gt; const &amp;rhs)
        : constant&lt;T&gt;(rhs.get())
        {}

        T&amp; get() const
        {
            return const_cast&lt;T&amp;&gt;(constant&lt;T&gt;::get());
        }

        T const *operator-&gt;() const {
            return constant&lt;T&gt;::operator-&gt;();
        }

        T *operator-&gt;() {
            return const_cast&lt;T *&gt;(constant&lt;T&gt;::operator-&gt;() );
        }
    };

    template &lt;class T&gt; 
    class fnresult
    {
    T m_T;
    public:
        explicit fnresult(T&amp; rhs) 
            : m_T(temporary&lt;T&gt;(rhs))
        {}

         // The cast's below is valid given that nobody ever really creates a 
        // const fnresult object
        fnresult(const fnresult&amp; rhs) 
            : m_T(temporary&lt;T&gt;(const_cast&lt;fnresult&amp;&gt;(rhs)))
        {}

        template&lt;class S&gt;
        fnresult(const fnresult&lt;S&gt; &amp;rhs)
           : m_T(temporary&lt;T&gt;(const_cast&lt;fnresult&lt;S&gt;&amp;&gt;(rhs)))
        {}

        T&amp; get()
        {
            return const_cast&lt;T &amp;&gt;(m_T);
        }

        T const &amp; get() const
        {
            return m_T;
        }

        T const *operator-&gt;() const {
            return &amp;m_T;
        }

        T *operator-&gt;() {
            return &amp;m_T;
        }
    private:
         fnresult &amp;operator=(fnresult const &amp;);
    };

    template &lt;class T&gt; struct enabled
    {
        operator temporary&lt;T&gt;()
        {
            return temporary&lt;T&gt;(static_cast&lt;T&amp;&gt;(*this));
        }
        template&lt;class S&gt;
        operator temporary&lt;S&gt;()
        {
            return temporary&lt;S&gt;(static_cast&lt;S&amp;&gt;(*this));
        }

        operator constant&lt;T&gt;() const
        {
            return constant&lt;T&gt;(static_cast&lt;const T&amp;&gt;(*this));
        }
        template&lt;class S&gt;
        operator constant&lt;S&gt;() const
        {
            return constant&lt;S&gt;(static_cast&lt;const S&amp;&gt;(*this));
        }

        operator fnresult&lt;T&gt;()
        {
            return fnresult&lt;T&gt;(static_cast&lt;T&amp;&gt;(*this));
        }
        template&lt;class S&gt;
        operator fnresult&lt;S&gt;()
        {
            return fnresult&lt;S&gt;(static_cast&lt;S&amp;&gt;(*this));
        }

    protected:
        enabled() {} // intended to be derived from
    };
}

#endif // MOJO_H_

// ------------------- testpointer.h --------
#if !defined(_TESTPTR_H)
#define _TESTPTR_H

#include &lt;iostream&gt;
#include &lt;string&gt;

typedef enum PtrStates { A_PTR = 0xFFFF,
                 DESTROYED_PTR = 0xDCDC,
                 UNINITED_PTR = 0xDEADC0DE,
                 ZERO = 0};

// class to watch for misuse of the pointers
class TestPtr {
   PtrStates m_ptr;
   const ::std::string m_className;

public:
   TestPtr()
   : m_ptr(UNINITED_PTR)
   , m_className(&quot;UnIdentified&quot;)
   {}

   TestPtr(::std::string const &amp;name)
   : m_ptr(UNINITED_PTR)
   , m_className(name)
   {}

   TestPtr(PtrStates rhs, ::std::string const &amp;name)
   : m_ptr(rhs)
   , m_className(name)
   {}

   TestPtr(TestPtr const &amp;rhs)
   : m_ptr(rhs.m_ptr)
   , m_className(rhs.m_className)
   {
       using ::std::cout;

       if (m_ptr == UNINITED_PTR) {
          cout &lt;&lt; __FILE__ &lt;&lt; '[' &lt;&lt; __LINE__ &lt;&lt; ']'
               &lt;&lt; &quot;WARNING CONSTRUCTIONG unitialized ptr from &quot;
               &lt;&lt; m_className &lt;&lt; &quot; unitialized ptr\n&quot;;
       }
       else if (m_ptr == ZERO) {
           cout &lt;&lt; __FILE__ &lt;&lt; '[' &lt;&lt; __LINE__ &lt;&lt; ']'
                &lt;&lt; &quot;WARNING! initialized from &quot;
                &lt;&lt; m_className &lt;&lt; &quot; dead temporary.\n&quot;;
       }
       else if (m_ptr == DESTROYED_PTR) {
           cout &lt;&lt; __FILE__ &lt;&lt; '[' &lt;&lt; __LINE__ &lt;&lt; ']'
                &lt;&lt; &quot;ERROR! initialized from &quot;
                &lt;&lt; m_className &lt;&lt; &quot; deleted value!\n&quot;;
       }
   }


   ~TestPtr()
   {
       using ::std::cout;
       if (m_ptr == UNINITED_PTR) {
          cout &lt;&lt; __FILE__ &lt;&lt; '[' &lt;&lt; __LINE__ &lt;&lt; ']'
               &lt;&lt; &quot;WARNING! DELETEING unitialized &quot;
               &lt;&lt; m_className &lt;&lt; &quot;ptr at &quot;
               &lt;&lt; this &lt;&lt; '\n';
       }
       else if (m_ptr == DESTROYED_PTR) {
          cout &lt;&lt; __FILE__ &lt;&lt; '[' &lt;&lt; __LINE__ &lt;&lt; ']'
               &lt;&lt; &quot;ERROR Double delete of &quot;
               &lt;&lt; m_className &lt;&lt; &quot; ptr at &quot;
               &lt;&lt; this &lt;&lt; '\n';
       }

       m_ptr = DESTROYED_PTR;
   }

   TestPtr &amp;operator=(TestPtr const &amp;rhs)
   {
       using ::std::cout;
       m_ptr = rhs.m_ptr;
       if (m_ptr == UNINITED_PTR) {
          cout &lt;&lt; __FILE__ &lt;&lt; '[' &lt;&lt; __LINE__ &lt;&lt; ']'
               &lt;&lt; &quot;WARNING assigning from &quot;
               &lt;&lt; m_className &lt;&lt; &quot; const unitialized ptr\n&quot;;
       }
       else if (m_ptr == ZERO) {
           cout &lt;&lt; __FILE__ &lt;&lt; '[' &lt;&lt; __LINE__ &lt;&lt; ']'
                &lt;&lt; &quot;WARNING! assigning from &quot;
                &lt;&lt; m_className &lt;&lt; &quot; const dead temporary.\n&quot;;
       } 
       else if (m_ptr == DESTROYED_PTR) {
           cout &lt;&lt; __FILE__ &lt;&lt; '[' &lt;&lt; __LINE__ &lt;&lt; ']'
                &lt;&lt; &quot;ERROR! assigning from &quot;
                &lt;&lt; m_className &lt;&lt; &quot; const deleted value!\n&quot;;
       }
       return *this;
    }

    TestPtr &amp;operator=(PtrStates rhs)
    {
       using ::std::cout;
       m_ptr = rhs;
       if (m_ptr == UNINITED_PTR) {
          cout &lt;&lt; __FILE__ &lt;&lt; '[' &lt;&lt; __LINE__ &lt;&lt; ']'
               &lt;&lt; &quot;WARNING assigning from &quot;
               &lt;&lt; m_className &lt;&lt; &quot; unitialized ptr\n&quot;;
       }
       else if (m_ptr == ZERO) {
           cout &lt;&lt; __FILE__ &lt;&lt; '[' &lt;&lt; __LINE__ &lt;&lt; ']'
                &lt;&lt; &quot;WARNING! assigning from &quot;
                &lt;&lt; m_className &lt;&lt; &quot; dead temporary.\n&quot;;
       } 
       else if (m_ptr == DESTROYED_PTR) {
           cout &lt;&lt; __FILE__ &lt;&lt; '[' &lt;&lt; __LINE__ &lt;&lt; ']'
                &lt;&lt; &quot;ERROR! assigning from &quot;
                &lt;&lt; m_className &lt;&lt; &quot; deleted value!\n&quot;;
       }
       return *this;
    }

    void reset() 
    {
        m_ptr = ZERO;
    }

    void validate() const
    {
       using ::std::cout;
       if (m_ptr == UNINITED_PTR) {
          cout &lt;&lt; __FILE__ &lt;&lt; '[' &lt;&lt; __LINE__ &lt;&lt; ']'
               &lt;&lt; &quot;INVALID DATA&quot;
               &lt;&lt; m_className &lt;&lt; &quot; unitialized ptr\n&quot;;
       }
       else if (m_ptr == ZERO) {
           cout &lt;&lt; __FILE__ &lt;&lt; '[' &lt;&lt; __LINE__ &lt;&lt; ']'
                &lt;&lt; &quot;INVALID DATA&quot;
                &lt;&lt; m_className &lt;&lt; &quot; dead temporary.\n&quot;;
       } 
       else if (m_ptr == DESTROYED_PTR) {
           cout &lt;&lt; __FILE__ &lt;&lt; '[' &lt;&lt; __LINE__ &lt;&lt; ']'
                &lt;&lt; &quot;INVALID DATA&quot;
                &lt;&lt; m_className &lt;&lt; &quot; deleted value!\n&quot;;
       }
    }

    void swap(TestPtr &amp;rhs)
    {
        PtrStates tmp(m_ptr);
        m_ptr = rhs.m_ptr;
        rhs = tmp;
    }
};

#endif

// ------------------ testclass.h ------------

#if !defined(_TESTCLASS_H)
#define _TESTCLASS_H

#include &lt;algorithm&gt;

#include &quot;testptr.h&quot;
#include &quot;mojo.h&quot;

class Y : public ::mojo::enabled&lt;Y&gt;
{
    TestPtr m_ptr;
public:
    Y() // default constructor
    : m_ptr(&quot;Y&quot;)
    {}

    Y(PtrStates ptr)
    : m_ptr(ptr, &quot;Y&quot;)
    {}

     Y(const Y&amp; rhs) // source is a const value
    : m_ptr(rhs.m_ptr)
    {}

    Y(::mojo::temporary&lt;Y&gt; src) // source is a temporary
        : m_ptr(src-&gt;m_ptr)
    {
        src-&gt;release();
    }

    Y(::mojo::fnresult&lt;Y&gt; src) // source is a fn result
        : m_ptr(src-&gt;m_ptr)
    {
        src-&gt;release();
    }

    ~Y()
    {}

    void swap( Y&amp;rhs)
    {
        using ::std::swap;
        swap(rhs.m_ptr, m_ptr);
    }

    Y &amp;operator=(Y const &amp; rhs) // source is a non const lvalue
    {
        using ::std::swap;

        Y tmp(rhs);
        tmp.swap(*this);
        return *this;
    }

    Y &amp;operator=(::mojo::temporary&lt;Y&gt; src) // source is a temporary
    {
        src-&gt;m_ptr.swap(m_ptr);
        src-&gt;release();

        return *this;
    }

    Y &amp;operator=(::mojo::fnresult&lt;Y&gt; src) // source is a fn result
    {
        return operator=(::mojo::temporary&lt;Y&gt;(src));
    }

    void validate() const
    {
        m_ptr.validate();
    }

private:
    void release() {
        m_ptr.reset();
    }
};

// test with binary operator +
::mojo::fnresult&lt;Y&gt; operator +(Y lhs, Y const &amp;rhs) {
    return lhs;
}

class Z : public Y
{
     TestPtr m_ptr;
public:
    Z() // default constructor
    : m_ptr(&quot;Z&quot;)
    {}

    Z(PtrStates ptr)
    : Y(ptr)
    , m_ptr(ptr, &quot;Z&quot;)
    {}

     Z(Z const&amp; rhs) 
    : Y(rhs)// source is a const value
    , m_ptr(rhs.m_ptr)
    {}

    Z(::mojo::temporary&lt;Z&gt; src)
    : Y(::mojo::temporary&lt;Y&gt;(src) )
    , m_ptr(src-&gt;m_ptr)             // source is a temporary
    {
        src-&gt;release();
    }

    Z(::mojo::fnresult&lt;Z&gt; src)
    : Y(::mojo::temporary&lt;Y&gt;(src.get()) )
    , m_ptr(src-&gt;m_ptr)             // source is a fn result
    {
        src-&gt;release();
    }

    ~Z()
    {}

    void swap(Z &amp;rhs)
    {
        using ::std::swap;

        Y::swap(rhs);
        swap(rhs.m_ptr, m_ptr);
    }

    Z &amp;operator=(Z const &amp;rhs) // source is a non const lvalue
    {
        using ::std::swap;

        Z tmp(rhs);
        tmp.swap(*this);

        return *this;
    }

    Z &amp;operator=(::mojo::temporary&lt;Z&gt; src) // source is a temporary
    {
        using ::std::swap;

        Y::operator=(::mojo::temporary&lt;Y&gt;(src) );
        src-&gt;m_ptr.swap(m_ptr);
        src-&gt;release();
        return *this;
    }

    Z &amp;operator=(::mojo::fnresult&lt;Z&gt; src) // source is a fn result
    {
        return operator=(::mojo::temporary&lt;Z&gt;(src));
    }

    void validate() const
    {
        Y::validate();
        m_ptr.validate();
    }
private:
    void release() {
        m_ptr.reset();
    }
};

class W : public ::mojo::enabled&lt;W&gt;
{
    TestPtr m_ptr;
public:
    W() // default constructor
    : m_ptr(&quot;W&quot;)
    {}

    W(PtrStates ptr)
    : m_ptr(ptr, &quot;W&quot;)
    {}

     W(::mojo::fnresult&lt;W&gt; src) // source is a temporary
        : m_ptr(src-&gt;m_ptr)
    {
        src-&gt;release();
    }

    W(::mojo::temporary&lt;W&gt; src) // source is a temporary
        : m_ptr(src-&gt;m_ptr)
    {
        src-&gt;release();
    }

    ~W()
    {}

    void swap( W&amp;rhs)
    {
        using ::std::swap;
        swap(rhs.m_ptr, m_ptr);
    }

    W &amp;operator=(::mojo::temporary&lt;W&gt; src) // source is a temporary
    {
        src-&gt;m_ptr.swap(m_ptr);
        src-&gt;release();
        return *this;
    }

    W &amp;operator=(::mojo::fnresult&lt;W&gt; src) // source is a fnresult temporary
    {
        return operator=(::mojo::temporary&lt;W&gt;(src) );
    }

    void validate() const
    {
        m_ptr.validate();
    }

private:
    void release() {
        m_ptr.reset();
    }

    W(const W&amp; rhs); // No copy construction!
    W &amp;operator=(W const &amp; rhs); // No assignment
};

// test with no data members.
class X : public ::mojo::enabled&lt;X&gt;
{
public:
    X() // default constructor
    {}

    X(::mojo::fnresult&lt;X&gt; src) // source is a temporary
    {
        src-&gt;release();
    }

    X(::mojo::temporary&lt;X&gt; src) // source is a temporary
    {
        src-&gt;release();
    }

    ~X()
    {}

    void swap( X&amp;rhs)
    {}

    X &amp;operator=(::mojo::temporary&lt;X&gt; src) // source is a temporary
    {
        src-&gt;release();
        return *this;
    }

    X &amp;operator=(::mojo::fnresult&lt;X&gt; src) // source is a fnresult temporary
    {
        return operator=(::mojo::temporary&lt;X&gt;(src) );
    }

    void validate() const
    {}

private:
    void release() {
        using ::std::cout;
    }

    X(const X&amp; rhs); // No copy construction!
    X &amp;operator=(X const &amp; rhs); // No assignment
};

class V : virtual public Y, public ::mojo::enabled&lt;V&gt;
{
     TestPtr m_ptr;
public:
    V() // default constructor
    : m_ptr(&quot;V&quot;)
    {}

    V(PtrStates ptr)
    : Y(ptr)
    , m_ptr(ptr,&quot;V&quot;)
    {}

    V(V const&amp; rhs) 
    : Y(rhs)// source is a const value
    , m_ptr(rhs.m_ptr)
    {}

    V(::mojo::temporary&lt;V&gt; src)
    : Y(::mojo::temporary&lt;Y&gt;(src) )
    , m_ptr(src-&gt;m_ptr)             // source is a temporary
    {
        src-&gt;release();
    }

    V(::mojo::fnresult&lt;V&gt; src)
    : Y(::mojo::temporary&lt;Y&gt;(src.get()))
    , m_ptr(src-&gt;m_ptr)            // source is a temporary
    {
        src-&gt;release();
    }

    virtual ~V()
    {}

    void swap(V &amp;rhs)
    {
        using ::std::swap;

        Y::swap(rhs);
        swap(rhs.m_ptr, m_ptr);
    }

    V &amp;operator=(V const &amp;rhs) // source is a non const lvalue
    {
        V tmp(rhs);
        tmp.swap(*this);

        return *this;
    }

    V &amp;operator=(::mojo::temporary&lt;V&gt; src) // source is a temporary
    {
        Y::operator=(::mojo::temporary&lt;Y&gt;(src) );
        src-&gt;m_ptr.swap(m_ptr);
        src-&gt;release();
        return *this;
    }

    V &amp;operator=(::mojo::fnresult&lt;V&gt; src) // source is a temporary
    {
        return operator=(::mojo::temporary&lt;V&gt;(src) );
    }

    void validate() const
    {
        Y::validate();
        m_ptr.validate();
    }
private:
    void release() {
        m_ptr.reset();
    }
};

class U : virtual public Y, virtual public V, public ::mojo::enabled&lt;U&gt;
{
     TestPtr m_ptr;
public:
    U() // default constructor
    : m_ptr(&quot;U&quot;)
    {}

    U(PtrStates ptr) // default constructor
    : Y(ptr)
    , V(ptr)
    , m_ptr(ptr, &quot;U&quot;)
    {}

    U(U const&amp; rhs) 
    : Y(rhs)// source is a const value
    , V(rhs)
    , m_ptr(rhs.m_ptr)
    {}

    U(::mojo::temporary&lt;U&gt; src)
    : Y(::mojo::temporary&lt;Y&gt;(src) )
    , V(::mojo::temporary&lt;V&gt;(src) )
    , m_ptr(src-&gt;m_ptr)             // source is a temporary
    {
        src-&gt;release();
    }

    U(::mojo::fnresult&lt;U&gt; src)
    : Y(::mojo::temporary&lt;Y&gt;(src.get()))
    , V(::mojo::temporary&lt;V&gt;(src.get()))
    , m_ptr(src-&gt;m_ptr)            // source is a temporary
    {
        src-&gt;release();
    }

    virtual ~U()
    { }

    void swap(U &amp;rhs)
    {
        //Y::swap(rhs);
        V::swap(rhs);
        rhs.m_ptr.swap(m_ptr);
    }

    U &amp;operator=(U const &amp;rhs) // source is a non const lvalue
    {
        using ::std::swap;

        U tmp(rhs);
        tmp.swap(*this);

        return *this;
    }

    U &amp;operator=(::mojo::temporary&lt;U&gt; src) // source is a temporary
    {
        //Y::operator=(::mojo::temporary&lt;Y&gt;(src) );
        V::operator=(::mojo::temporary&lt;V&gt;(src) );
        src-&gt;m_ptr.swap(m_ptr);
        src-&gt;release();
        return *this;
    }

    U &amp;operator=(::mojo::fnresult&lt;U&gt; src) // source is a temporary
    {
        return operator=(::mojo::temporary&lt;U&gt;(src) );
    }

    void validate() const
    {
        Y::validate();
        V::validate();
        m_ptr.validate();
    }
private:
    void release() {
        m_ptr.reset();
    }
};
#endif

// ----------------- main.cpp ----------------
#include &quot;mojo.h&quot;
#include &lt;iostream&gt;
#include &lt;vector&gt;
#include &lt;cassert&gt;

#include &quot;testclass.h&quot;
using namespace std;

// stupid macro to print the line, and then execute it.
#define DO(x)  cout &lt;&lt; (#x) &lt;&lt; &quot;\n&quot;; x ; cout &lt;&lt; '\n';


const Y MakeConstY()
{
    DO(return Y(A_PTR));
}

::mojo::fnresult&lt;Y&gt; MakeY()
{
    DO(Y x(A_PTR));
    DO(return x);
}

void TakeConstY(const Y&amp;)
{
}

void TakeY(Y&amp;)
{
}

const Z MakeConstZ()
{
    DO(return Z(A_PTR));
}


::mojo::fnresult&lt;Z&gt; MakeZ()
{
    DO(Z x(A_PTR));
    DO(return x);
}

void TakeConstZ( Z const &amp; rhs)
{
}

void TakeZ( Z &amp; rhs)
{
}

::mojo::fnresult&lt;W&gt; MakeW()
{
    DO(W x(A_PTR));
    DO(return x);
}

::mojo::fnresult&lt;U&gt; MakeU()
{
    DO(U x(A_PTR));
    DO(return x);
}

::mojo::fnresult&lt;V&gt; MakeV()
{
    DO(V x(A_PTR));
    DO(return x);
}

void Discriminate(Y&amp;) {}
void Discriminate(mojo::temporary&lt;Y&gt;) {}
void Discriminate(mojo::constant&lt;Y&gt;) {}
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////

int main()
{
    DO(Y nonConstLValue(A_PTR));
    DO(const Y constLValue(A_PTR));

    DO(Y y1(constLValue));
    DO(Y y2(nonConstLValue));
    DO(Y y3(MakeConstY()));
    DO(Y y4(MakeY()));

    DO(y4.validate() );

    //TakeConstY(Y());
    //TakeConstY(MakeY());

    //TakeY(Y());
    //TakeY(MakeY());
    {
        cout &lt;&lt; &quot;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~&quot; &lt;&lt; endl;
        DO(Discriminate(Y(A_PTR))); // calls Discriminate(mojo::temporary&lt;Y&gt;)
        DO(Discriminate(MakeY())); // calls Discriminate(mojo::temporary&lt;Y&gt;)
        DO(Discriminate(constLValue)); // calls Discriminate(mojo::constant&lt;Y&gt;)
        DO(Discriminate(nonConstLValue)); // calls Discriminate(Y&amp;)
        cout &lt;&lt; &quot;&lt;&gt;&lt;&gt;&lt;&gt;&lt;&gt;&lt;&gt;&lt;&gt;&lt;&gt;&lt;&gt;&lt;&gt;&lt;&gt;&lt;&gt;&lt;&gt;&lt;&gt;&lt;&gt;&lt;&gt;&lt;&gt;&lt;&gt;&lt;&gt;&lt;&gt;&lt;&gt;&quot; &lt;&lt; endl;
    }
    {
        cout &lt;&lt; &quot;=======================================&quot; &lt;&lt; endl;
        DO(y1 = constLValue);
        DO(y2 = nonConstLValue);
        DO(y3 = MakeConstY());
        DO(y4 = MakeY());
        DO(y4.validate() );
        cout &lt;&lt; &quot;---------------------------------------&quot; &lt;&lt; endl;
    }

    #if 1
    {
        cout &lt;&lt; &quot;+++++++++++++++++++++++++++++++++++++++&quot; &lt;&lt; endl;
        DO(Z nonConstZLValue(A_PTR));
        DO(const Z constZLValue(A_PTR));

        DO(Z z1(constZLValue));
        DO(Z z2(nonConstZLValue));
        DO(Z z3(MakeConstZ()));
        DO(Z z4(MakeZ()));
        DO(z4.validate() );
        cout &lt;&lt; &quot;#######################################&quot; &lt;&lt; endl;

        {
            cout &lt;&lt; &quot;$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$&quot; &lt;&lt; endl;
            DO(z1 = constZLValue);
            DO(z2 = nonConstZLValue);
            DO(z3 = MakeConstZ());
            DO(z4 = MakeZ());
            DO(z4.validate() );
            cout &lt;&lt; &quot;&#64;&#64;&#64;&#64;&#64;&#64;&#64;&#64;&#64;&#64;&#64;&#64;&#64;&#64;&#64;&#64;&#64;&#64;&#64;&#64;&#64;&#64;&#64;&#64;&#64;&#64;&#64;&#64;&#64;&#64;&#64;&#64;&#64;&#64;&#64;&#64;&#64;&#64;&#64;&quot; &lt;&lt; endl;
        }
    }
    #endif

    {
        cout &lt;&lt; &quot;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!&quot; &lt;&lt; endl;
        DO(y1 = y2 + y3);
        DO(y1.validate() );

        DO(y1 = y2 + y3 + y4);
        DO(y1.validate() );

        DO(y1 = Y(A_PTR) + y3 + y4);
        DO(y1.validate() );

        DO(y1 = MakeY() + MakeY() + MakeY());
        DO(y1.validate() );
        cout &lt;&lt; &quot;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%&quot; &lt;&lt; endl;

    }


    {
        cout &lt;&lt; &quot;TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT&quot; &lt;&lt; endl;
        DO(Y y1(A_PTR));
        DO( TakeY(y1) );
        DO(TakeConstY(Y(A_PTR) ));
        DO(Z z1(A_PTR));
        DO(TakeZ( z1 ));
        DO(TakeConstZ(Z(A_PTR) ));
        cout &lt;&lt; &quot;000000000000000000000000000000000000000&quot; &lt;&lt; endl;
    }
    cout &lt;&lt; &quot;sizeof(Y) = &quot; &lt;&lt; sizeof (Y) &lt;&lt; '\n';
    cout &lt;&lt; &quot;sizeof(Z) = &quot; &lt;&lt; sizeof (Z) &lt;&lt; '\n';
    cout &lt;&lt; &quot;sizeof(TestPtr) = &quot; &lt;&lt; sizeof (TestPtr) &lt;&lt; '\n';
    {
        DO(W w1(A_PTR));
        DO(W w2(MakeW())); // ok construction from temporary.
        DO(w1 = MakeW()); // ok assignment from fnresult temporary.
        //DO(W w3(w1)); // fails to link.
        //DO(w1 = w2); // fails to link.
    }
    {
        cout &lt;&lt; &quot;GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG&quot; &lt;&lt; endl;
        typedef ::std::vector&lt;Y&gt; Y_Vec_t;

        DO(Y_Vec_t y_vec);

        DO(y_vec.push_back(MakeY() ));

        DO(y_vec[0].validate());
        cout &lt;&lt; &quot;HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH&quot; &lt;&lt; endl;
    }

    {
        cout &lt;&lt; &quot;IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII&quot; &lt;&lt; endl;

        DO( V v1(A_PTR));
        DO( v1 = MakeV());
        DO( V v2(MakeV()));
        cout &lt;&lt; &quot;RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR&quot; &lt;&lt; endl;
    }
    {
        cout &lt;&lt; &quot;DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD&quot; &lt;&lt; endl;

        DO( U u1(A_PTR));
        DO( u1 = MakeU());
        DO( U u2(MakeU()));

        cout &lt;&lt; &quot;RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR&quot; &lt;&lt; endl;
    }

    DO(cout &lt;&lt; sizeof(Y) &lt;&lt; &quot; &quot;);
    DO(cout &lt;&lt; sizeof(Z) &lt;&lt; &quot; &quot;);
    DO(cout &lt;&lt; sizeof(W) &lt;&lt; &quot; &quot;);
    DO(cout &lt;&lt; sizeof(X) &lt;&lt; &quot; &quot;);
    DO(cout &lt;&lt; sizeof(TestPtr) &lt;&lt; &quot;\n&quot;);
}
</pre>
</div>
</div>
<hr class="footer" />
<div class="footer">
<a class="reference" href="move.rst">View document source</a>.
Generated on: 2004-02-17 14:52 UTC.
Generated by <a class="reference" href="http://docutils.sourceforge.net/">Docutils</a> from <a class="reference" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> source.
</div>
</body>
</html>
