<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>
<head>
    <title>Proposal to add l-value member function
    qualifier</title>
</head>

<body>
    <div>
        <h1>A proposal to add l-value member function qualifier</h1>

        <p><tt>Author:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Bronek Kozicki &lt;<a href=
        "mailto:brok@rubikon.pl">brok@rubikon.pl</a>&gt;</tt><br>
         <tt>Doc. no.:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;N1784=05-0044</tt><br>
         <tt>Date:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2005-04-15</tt><br>
         <tt>Working Group:&nbsp;&nbsp;Evolution</tt></p>

        <h2>Abstract</h2>

        <p>This proposal supersedes document N1676. In N1676 I proposed fix for certain asymmetry in the language
        that makes it impossible to disallow call of copy
        assignment operator on r-value of user defined type (e.g. &quot;<tt>A() = A();</tt>&quot;). 
		After discussion with members of BSI panel I decided that proposed 
		resolution (i.e. allowing copy assignment operator to be declared as 
		non-member function) would add significant complexity into language without 
		reasonable gain, given obvious and less obvious issues with name hiding, 
		inheritance, etc. that are partly discussed in section 4 of N1676. There 
		was however alternative solution mentioned in section 4.1 that I'm going 
		to elaborate in following
        proposal.</p>

        <h1>Contents</h1>

        <p><a href="#motivation">1. Motivation</a><br>
         <a href="#proposal">2. Proposal</a><br>
         <a href="#overloading">3. Overloading</a><br>
         <a href="#endnote">4. Ending note</a></p>

        <h2><a name="motivation"></a><b>1. Motivation</b></h2>

        <p>Currently C++ does not have any means to prevent member
        functions from being called on r-value of user defined
        type. Typical workaround for this problem (often applied when overloading operators) is to declare function as a non-member 
		function
        taking non-const reference to user-defined type. Although this is frequently valid solution, it
        may not always be applied, or is sometimes sub-optimal:</p>

        <ol>
            <li>there is different syntax to call member and
            non-member function, unless it is overloaded
            operator</li>

            <li>member functions have different properties than
            non-member functions (e.g. member hiding)</li>

            <li>some operators may not be overloaded as a
            non-member functions (e.g. assignment, parentheses)</li>
        </ol>

        <p>There is obviously some asymmetry in the language that
        does allow one to define function parameter as non-const
        reference, thus preventing r-value from being passed to
        function or allowing separate overloads for l-value and
        r-value argument, but there are no means to prevent member
        function from being called on r-value. Here is sample program
        that would actually benefit from ability to declare
        overloaded assignment operator that may be called only on
        l-value:</p>

<blockquote>
           <pre>
#include &lt;cstdio&gt;

template &lt;typename T, typename V&gt;
void f(T t, V v)
{
  // perform some calculation and
  // store result into reference returned by t()
  t() = v * 2;
}

class M
{
  struct K
  {
    int i;
    K(int i) : i (i) {}
  };
  // unable to disable assignment to rvalue of type K
  
  static K k;
public:
  static K&amp; g1()
  {
    return k;
  }
  static K g2()
  {
    return k; // returning copy!
  }
  static int&amp; g3()
  {
    return k.i;
  }
  static float g4()
  {
    return k.i; // returning copy!
  }
  static void show()
  {
    std::printf("K::k.i == %i\n", k.i);
  }
};

M::K M::k(1);
int main()
{
  f(M::g1, 30);    // OK
  M::show();       // 60
  
  f(M::g2, 31);    // should be an error, but compiles fine
  M::show();       // 60, which is unexpected output
  
  f(M::g3, 32);    // OK
  M::show();       // 64
  
  // f(M::g4, 3.14);    // error, as it should be
}
</pre>
        </blockquote>

        <p>Following proposal is an attempt to remove demonstrated
        problem from C++ .</p>

        <h2><a name="proposal"></a><b>2. Proposal</b></h2>

        <p>Proposed resolution is to introduce additional qualifier that could be 
		applied to non-static member function 
		(clause 9.3.1/3). This
        qualifier would mean "member function may be called on
        l-value only" and will be further called <i>l-value qualifier</i>. Proposed actual syntax is to reuse
        ampersand character in location reserved for cv-qualifiers of non-static 
		member function. In <a href="#motivation">motivation</a> example it could
        be used to define overloaded copy assignment operator, as demonstrated 
		below:</p>
<blockquote>
           <pre>
// ... as in motivation example
class M
{
  struct K
  {
    int i;
    K(int i) : i (i) {}
    K&amp; operator=(const K&amp; rh) &amp; // l-value qualifier
    {
      i = rh.i;
      return *this;
    }
  };
// ... as in motivation example
int main()
{
  f(M::g2, 31); // compilation error
}
</pre>
</blockquote>
        <p>Here is proposed semantics of l-value qualifier:</p>
<ol>
        <li> its primary meaning is to disable member function call
        on object that is an r-value</li>

        <li> it does not change type of <tt>this</tt> expression
        used inside member function denoted with this qualifier</li>

        <li> l-value qualifier can be freely mixed with
        cv-qualifiers; const, volatile and l-value properties of
        type are orthogonal thus there's no reason to introduce
        any special limitations.</li>
</ol>

<p>Proposed qualifier will allow class author to mark any
        member function as "to be called on l-values only"; this in
        effect will give him power to decide "how powerful
        temporary value may be", thus limiting number of temporary
        values created by class user. This ability should not be
        overused. Rule of thumb is : <i>use l-value qualifier only
        for function whose sole purpose if to modify state of the
        object</i> or <i>overloads of selected operators</i>. For example: l-value
        qualifier could be used to denote non-static member function returning void
        that does not take non-const reference or non-const pointer
        as its argument and that modifies state of the object
        without any side effects. It could be also used to declare
        overload of assignment operator, compound assignment (i.e.
        "+=", "*=" etc.) or take address operator (i.e.
        "&amp;"), thus providing class behaviour closer to that of built-in 
types. I believe this has important implications for generic programming.</p>

        <h2><a name="overloading"></a><b>3. Overloading</b></h2>

        
        <p>Addition of another qualifier raises questions about
        possible complication of function overloading rules. There
        could be two solutions:</p>
<ol>
     <li> do not allow overloading. This could be easily achieved
        adding another bullet to clause 13.1 :    
        <i>member functions that differ only by presence or absence
        of lvalue qualifier are equivalent</i>. Sample
        code using l-value qualifier would be as follows:
<blockquote>
        <pre>
struct A
{
  void f(const int&amp;) &amp; {}
  void f(int&amp;) {} // called in line denoted // 1 below

  void g(int&amp;) &amp; {}
  // void g(int&amp;) {} - compiler error
};

int main()
{
  int i;
  A a;
  a.f(i); // 1
}
</pre>
        </blockquote>
        </li>

       <li> allow overloading. As there are no conversions from
        rvalue to lvalue, overloading rule would not need to take
        conversion into account. It should also have very low priority in order 
		not to change meaning of programs when l-value qualifier is added to 
		non-static class member functions used by such programs. This would 
		allow following program to perform special optimization when data are 
		copied from temporary value:
		<blockquote>
		<pre>
struct A
{
  A(char * = 0);
  ~A();
  void copy(A&amp;) &amp;;
  void copy(A&amp;); // performs swap
};

int main()
{
  A a;
  A(new char[10000000]).copy(a); // fast!
}

		</pre>
		</blockquote>
		</li>
        
</ol>        
<h2><a name="endnote"></a>4<b>. Ending note</b></h2>
Although problem that this proposal strive to solve is small, it is real and 
surprising, especially for novice programmers. Proposed solution is still work in progress. 
Even if it might seem complicated, I believe that simple solution is possible. 
    </div>
</body>
</html>