Topic: A proposal to add mutable function and mutable


Author: "Vicente J. Botet Escriba" <vicente.botet@wanadoo.fr>
Date: Sat, 27 Apr 2013 17:13:03 +0200
Raw View
This is a multi-part message in MIME format.
--------------060608050404070805080906
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: quoted-printable

Le 27/04/13 16:02, Hariharan Subramanian a =E9crit :
> A proposal to add mutable function and mutable code section
>
> *Problem:*
>
> class Member; //definition elsewhere
>
> class A
> {
> private:
> Member *member;
> //Other variables
> public:
> A() { member =3D nullptr; }
> const Member* A::GetMember() const;
> //Other functions
> };
>
> const Member* A::GetMember() const {
> if(member =3D=3D nullptr) {
> //lazy initialize member
> }
> return member;
> }
>
> The above code results in compilation error as we modify a member=20
> variable within a const function.
>
> *Current solutions and their problems:*
>
> *Current Solution 1:*
> Make member variable mutable.
> *The problem with this solution:*
> This defeats the very purpose of having const member functions.=20
> Semantically it is a constant and other const functions should not=20
> modify it. Making it mutable gives any function the power to modify=20
> it. If there are lot of lazy member initializations then all those=20
> member variables need to be declared mutable and that makes the=20
> program error prone.
>
> *Current Solution 2:*
> Let the return value be const but the function be non-const. Hence the=20
> prototype becomes const Member* A::GetMember().
> *The problem with this solution:*
> Consider the code below.
> void foo(const A &obj) {
> const Member &m1 =3D obj.GetMember(); //Compilation error!
> }
> To avoid the above compilation error const_cast the 'obj' or pass A=20
> &obj instead of const A &obj. If we do a const_cast it would mean that=20
> all the functions that have const A& should do a const_cast to call=20
> GetMember. This results in a difficult to maintain code. The other=20
> alternative of passing A &obj postpones the problem to the callee of=20
> foo. Now that callee function has to make the same decision. This has=20
> the cascading effect.
>
> *Proposed solution:*
> We can see that none of the above solutions are desirable. We can=20
> introduce the concept of mutable function and mutable code section.
>
> *Solution using mutable code section:*
>
> const Member* A::GetMember() const {
> mutable {
> if(member =3D=3D nullptr) {
> //lazy initialize member
> }
> }
> return member;
> }
>
> The above mutable code section tells the compiler to suspend checking=20
> if variables are modified or not.
>
> *Solution using mutable function:*
> Introduce a new private mutable member function LazyInitializeMember.=20
> The code will be changed like this.
>
> void A::LazyInitializeMember() mutable {
> //lazy intialize member
> }
>
> const Member* A::GetMember() const {
> LazyInitializeMember();
> return member;
> }
>
I've not analyzed all your proposal. Would something like the following=20
work for you?

T& as_mutable() const { return const_cast<T&>(*this);}

*Solution using mutable code section:*

const Member* A::GetMember() const {
if(member =3D=3D nullptr) {
             //lazy initialize member
             as_mutable() =3D ...
}
return member;
}

*Solution using mutable function:

*
void A::LazyInitializeMember() {
//lazy intialize member
}

const Member* A::GetMember() const {
as_mutable().LazyInitializeMember();
return member;
}

Best,
Vicente

--=20

---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/?hl=3Den.



--------------060608050404070805080906
Content-Type: text/html; charset=ISO-8859-1

<html>
  <head>
    <meta content="text/html; charset=ISO-8859-1"
      http-equiv="Content-Type">
  </head>
  <body bgcolor="#FFFFFF" text="#000000">
    <div class="moz-cite-prefix">Le 27/04/13 16:02, Hariharan
      Subramanian a &eacute;crit&nbsp;:<br>
    </div>
    <blockquote
      cite="mid:32f25112-751e-4c0f-b390-4aa876442173@isocpp.org"
      type="cite">
      <div><font size="4">A proposal to add mutable function and mutable
          code section</font></div>
      <div><br>
      </div>
      <div><b>Problem:</b></div>
      <div><br>
      </div>
      <div>class Member; //definition elsewhere</div>
      <div><br>
      </div>
      <div>class A</div>
      <div>{</div>
      <div>private:</div>
      <div><span class="Apple-tab-span" style="white-space:pre"> </span>Member
        *member;</div>
      <div><span class="Apple-tab-span" style="white-space:pre"> </span>//Other
        variables</div>
      <div>public:</div>
      <div><span class="Apple-tab-span" style="white-space:pre"> </span>A()
        { member = nullptr; }</div>
      <div><span class="Apple-tab-span" style="white-space:pre"> </span>const
        Member* A::GetMember() const;</div>
      <div><span class="Apple-tab-span" style="white-space:pre"> </span>//Other
        functions</div>
      <div>};</div>
      <div><br>
      </div>
      <div>const Member* A::GetMember() const {</div>
      <div><span class="Apple-tab-span" style="white-space:pre"> </span>if(member
        == nullptr) {</div>
      <div><span class="Apple-tab-span" style="white-space:pre"> </span>//lazy
        initialize member</div>
      <div><span class="Apple-tab-span" style="white-space:pre"> </span>}</div>
      <div><span class="Apple-tab-span" style="white-space:pre"> </span>return
        member;</div>
      <div>}</div>
      <div><br>
      </div>
      <div>The above code results in compilation error as we modify a
        member variable within a const function.</div>
      <div><br>
      </div>
      <div><b>Current solutions and their problems:</b></div>
      <div><br>
      </div>
      <div><b>Current Solution 1:</b></div>
      <div>Make member variable mutable.</div>
      <div><b>The problem with this solution:</b></div>
      <div>This defeats the very purpose of having const member
        functions. Semantically it is a constant and other const
        functions should not modify it. Making it mutable gives any
        function the power to modify it. If there are lot of lazy member
        initializations then all those member variables need to be
        declared mutable and that makes the program error prone.</div>
      <div><br>
      </div>
      <div><b>Current Solution 2:</b></div>
      <div>Let the return value be const but the function be non-const.
        Hence the prototype becomes const Member* A::GetMember().</div>
      <div><b>The problem with this solution:</b></div>
      <div>Consider the code below.</div>
      <div>void foo(const A &amp;obj) {</div>
      <div><span class="Apple-tab-span" style="white-space:pre"> </span>const
        Member &amp;m1 = obj.GetMember(); //Compilation error!</div>
      <div>}</div>
      <div>To avoid the above compilation error const_cast the 'obj' or
        pass A &amp;obj instead of const A &amp;obj. If we do a
        const_cast it would mean that all the functions that have const
        A&amp; should do a const_cast to call GetMember. This results in
        a difficult to maintain code. The other alternative of passing A
        &amp;obj postpones the problem to the callee of foo. Now that
        callee function has to make the same decision. This has the
        cascading effect.</div>
      <div><br>
      </div>
      <div><b>Proposed solution:</b></div>
      <div>We can see that none of the above solutions are desirable. We
        can introduce the concept of mutable function and mutable code
        section.</div>
      <div><br>
      </div>
      <div><b>Solution using mutable code section:</b></div>
      <div><br>
      </div>
      <div>const Member* A::GetMember() const {</div>
      <div><span class="Apple-tab-span" style="white-space:pre"> </span>mutable
        {</div>
      <div><span class="Apple-tab-span" style="white-space:pre"> </span>if(member
        == nullptr) {</div>
      <div><span class="Apple-tab-span" style="white-space:pre"> </span>//lazy
        initialize member</div>
      <div><span class="Apple-tab-span" style="white-space:pre"> </span>}</div>
      <div><span class="Apple-tab-span" style="white-space:pre"> </span>}</div>
      <div><span class="Apple-tab-span" style="white-space:pre"> </span>return
        member;</div>
      <div>}</div>
      <div><br>
      </div>
      <div>The above mutable code section tells the compiler to suspend
        checking if variables are modified or not.</div>
      <div><br>
      </div>
      <div><b>Solution using mutable function:</b></div>
      <div>Introduce a new private mutable member function
        LazyInitializeMember. The code will be changed like this.</div>
      <div><br>
      </div>
      <div>void A::LazyInitializeMember() mutable {</div>
      <div><span class="Apple-tab-span" style="white-space:pre"> </span>//lazy
        intialize member</div>
      <div>}</div>
      <div><br>
      </div>
      <div>const Member* A::GetMember() const {</div>
      <div><span class="Apple-tab-span" style="white-space:pre"> </span>LazyInitializeMember();</div>
      <div><span class="Apple-tab-span" style="white-space:pre"> </span>return
        member;</div>
      <div>}</div>
      <div><br>
      </div>
    </blockquote>
    I've not analyzed all your proposal. Would something like the
    following work for you?<br>
    <br>
    T&amp; as_mutable() const { return const_cast&lt;T&amp;&gt;(*this);}<br>
    <br>
    <div><b>Solution using mutable code section:</b></div>
    <br>
    <div>const Member* A::GetMember() const {</div>
    <span class="Apple-tab-span" style="white-space:pre"> </span>if(member
    == nullptr) {
    <div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; //lazy initialize member<br>
      &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; as_mutable() = ...<br>
    </div>
    <div><span class="Apple-tab-span" style="white-space:pre"> </span>}</div>
    <span class="Apple-tab-span" style="white-space:pre"> </span>return
    member;
    <div>}</div>
    <br>
    <div><b>Solution using mutable function:<br>
        <br>
      </b></div>
    <div>void A::LazyInitializeMember() {</div>
    <div><span class="Apple-tab-span" style="white-space:pre"> </span>//lazy
      intialize member</div>
    <div>}</div>
    <div><br>
    </div>
    <div>const Member* A::GetMember() const {</div>
    <div><span class="Apple-tab-span" style="white-space:pre"> </span>as_mutable().LazyInitializeMember();</div>
    <div><span class="Apple-tab-span" style="white-space:pre"> </span>return
      member;</div>
    <div>}</div>
    &nbsp;
    <br>
    Best,<br>
    Vicente<br>
  </body>
</html>

<p></p>

-- <br />
&nbsp;<br />
--- <br />
You received this message because you are subscribed to the Google Groups &quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href="http://groups.google.com/a/isocpp.org/group/std-proposals/?hl=en">http://groups.google.com/a/isocpp.org/group/std-proposals/?hl=en</a>.<br />
&nbsp;<br />
&nbsp;<br />

--------------060608050404070805080906--

.


Author: Martinho Fernandes <martinho.fernandes@gmail.com>
Date: Sat, 27 Apr 2013 17:27:19 +0200
Raw View
--047d7bb043ae93628b04db5949b4
Content-Type: text/plain; charset=ISO-8859-1

On Sat, Apr 27, 2013 at 5:13 PM, Vicente J. Botet Escriba <
vicente.botet@wanadoo.fr> wrote:

> I've not analyzed all your proposal. Would something like the following
> work for you?
>
> T& as_mutable() const { return const_cast<T&>(*this);}
>

No, that's broken. const_cast is not the same as mutable. The two have
different semantics, and unsurprisingly different use cases.

const_cast cannot cheat: if a variable is in a const object it cannot be
changed, not even through the reference you magic up with const_cast.
Attempting to do so results in undefined behaviour. Changing the reference
type with const_cast does not change the mutability of the variable:
const_cast merely removes the const from the type. The use case for this is
dealing with legacy APIs that are known not to mutate data, but "forgot" to
advertise it in their APIs.

On the other hand, mutable *is*, in a way, cheating. Variables declared
mutable can always be changed, even on const objects. That's the use case
here.

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/?hl=en.



--047d7bb043ae93628b04db5949b4
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><br><div class=3D"gmail_extra">On Sat, Apr 27, 2013 at 5:1=
3 PM, Vicente J. Botet Escriba <span dir=3D"ltr">&lt;<a href=3D"mailto:vice=
nte.botet@wanadoo.fr" target=3D"_blank">vicente.botet@wanadoo.fr</a>&gt;</s=
pan> wrote:<br>
<div class=3D"gmail_quote"><blockquote class=3D"gmail_quote" style=3D"margi=
n:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
 =20
   =20
 =20
  <div bgcolor=3D"#FFFFFF" text=3D"#000000">I&#39;ve not analyzed all your =
proposal. Would something like the
    following work for you?<br>
    <br>
    T&amp; as_mutable() const { return const_cast&lt;T&amp;&gt;(*this);}<br=
></div></blockquote><div>=A0</div><div>No, that&#39;s broken. const_cast is=
 not the same as mutable. The two have different semantics, and unsurprisin=
gly different use cases.<br>
</div><div><br>const_cast cannot cheat: if a variable is in a const object =
it cannot be changed, not even through the reference you magic up with cons=
t_cast. Attempting to do so results in undefined behaviour. Changing the re=
ference type with const_cast does not change the mutability of the variable=
: const_cast merely removes the const from the type. The use case for this =
is dealing with legacy APIs that are known not to mutate data, but &quot;fo=
rgot&quot; to advertise it in their APIs.<br>
<br></div><div>On the other hand, mutable *is*, in a way, cheating. Variabl=
es declared mutable can always be changed, even on const objects. That&#39;=
s the use case here.</div></div></div></div>

<p></p>

-- <br />
&nbsp;<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/?hl=3Den">http://groups.google.com/a/isocpp.org/group/std-pro=
posals/?hl=3Den</a>.<br />
&nbsp;<br />
&nbsp;<br />

--047d7bb043ae93628b04db5949b4--

.


Author: Martinho Fernandes <martinho.fernandes@gmail.com>
Date: Sat, 27 Apr 2013 17:31:19 +0200
Raw View
--002354187304dad97304db5957b2
Content-Type: text/plain; charset=ISO-8859-1

On Sat, Apr 27, 2013 at 4:02 PM, Hariharan Subramanian <tohari@gmail.com>wrote:

> If there are lot of lazy member initializations then all those member
> variables need to be declared mutable and that makes the program error
> prone.
>

If there are lots of lazy member initializations it is time to start seeing
the pattern here and making a lazy_initialized template.

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/?hl=en.



--002354187304dad97304db5957b2
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">On Sat, Apr 27, 2013 at 4:02 PM, Hariharan Subramanian <sp=
an dir=3D"ltr">&lt;<a href=3D"mailto:tohari@gmail.com" target=3D"_blank">to=
hari@gmail.com</a>&gt;</span> wrote:<br><div class=3D"gmail_extra"><div cla=
ss=3D"gmail_quote">
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex">If there are lot of lazy member initializati=
ons then all those member variables need to be declared mutable and that ma=
kes the program error prone.<span class=3D"HOEnZb"><font color=3D"#888888">=
 <br>

</font></span></blockquote></div><br></div><div class=3D"gmail_extra">If th=
ere are lots of lazy member initializations it is time to start seeing the =
pattern here and making a lazy_initialized template.<br></div></div>

<p></p>

-- <br />
&nbsp;<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/?hl=3Den">http://groups.google.com/a/isocpp.org/group/std-pro=
posals/?hl=3Den</a>.<br />
&nbsp;<br />
&nbsp;<br />

--002354187304dad97304db5957b2--

.


Author: Hariharan Subramanian <tohari@gmail.com>
Date: Sun, 28 Apr 2013 00:48:40 +0530
Raw View
--001a11c26804f6d4bb04db5c84e0
Content-Type: text/plain; charset=ISO-8859-1

Lazy initialization is one use case for which mutable function is a
solution. Mutable function/code section is useful for the following types
of functions.

void Class::DoOperation() const {
     //Object is in state x
mutable {
     //Change the state to y. Do the operation
}
     //Restore the state to x (or an equivalent state x')
}

An example:
The example is a little long. But it explains the use and power of mutable
function nicely.

Consider a Linked list with 2 pointers - one next pointer and one forward
pointer - for each node. The forward pointer points to some arbitrary node
ahead of it. The operation to be performed is clone.

struct Node {
int num;
Node *next, *forward;
}

A sample list is shown below. The next pointers point like this.
10 -> 20 -> 30 -> 40 -> 50
The forward pointers point like this
10 -> 30 & 20 -> 50. All other forward pointers are nullptrs. 30's forward
pointer cannot point to 20 as it is behind it.

There are 2 algorithms that can do it efficiently in O(n) time and O(1)
space (There is an algorithm that does not modify the list even
temporarily. But that uses O(n) time and O(n) space). But they modify the
Linked list during cloning and restore it to the original state in the end.
I am giving only algorithm 1 for the sake of brevity. The pseudo code is
given in the end.

In algorithm 1 next pointer is modified and restored to the original state
for cloning.
In algorithm 2 forward pointer is modified and restored to the original
state for cloning.

It is clear that none of the pointers are mutable whereas the clone
operation is mutable. The worse thing is the variable that is mutable
depends on the algorithm chosen and not on the meaning of the class.
Semantically this is unacceptable. The mutable function provides the
alternate.

In my proposal I erroneously mentioned that const_cast can be
surreptitiously used for object modification. I stand corrected on this and
thanks to Martinho Fernandes for pointing it out.

//Pseudo code for algorithm 1.
void LinkedList::CloneAlgo1() mutable {
1. In pass 1 duplicate the nodes and make the next pointers point to the
duplicate nodes
The list becomes 10 -> 10' -> 20 -> 20' -> 30 -> 30' -> 40 -> 40' -> 50 ->
50'
The forward pointers do not change. 10 -> 30 & 20 -> 50
2. pass 2
if(even node's forward ptr != nullptr)
          evenNode->next->forwardPtr = evenNode->forwardPtr->next;
The following forward pointers get added. 10' -> 30' & 20' -> 50'
3. In pass 3 split the list into odd list and even list.
And we cloned.
}

Hariharan S

On Sat, Apr 27, 2013 at 9:01 PM, Martinho Fernandes <
martinho.fernandes@gmail.com> wrote:

> On Sat, Apr 27, 2013 at 4:02 PM, Hariharan Subramanian <tohari@gmail.com>wrote:
>
>> If there are lot of lazy member initializations then all those member
>> variables need to be declared mutable and that makes the program error
>> prone.
>>
>
> If there are lots of lazy member initializations it is time to start
> seeing the pattern here and making a lazy_initialized template.
>
> --
>
> ---
> You received this message because you are subscribed to a topic in the
> Google Groups "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this topic, visit
> https://groups.google.com/a/isocpp.org/d/topic/std-proposals/8TGpsfF5aXs/unsubscribe?hl=en
> .
> To unsubscribe from this group and all its topics, send an email to
> std-proposals+unsubscribe@isocpp.org.
> To post to this group, send email to std-proposals@isocpp.org.
> Visit this group at
> http://groups.google.com/a/isocpp.org/group/std-proposals/?hl=en.
>
>
>

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/?hl=en.



--001a11c26804f6d4bb04db5c84e0
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">Lazy initialization is one use case for which mutable func=
tion is a solution. Mutable function/code section is useful for the followi=
ng types of functions.<div><br></div><div>void Class::DoOperation() const {=
</div>
<div style>=A0 =A0 =A0//Object is in state x</div><div style>mutable {</div=
><div style>=A0 =A0 =A0//Change the state to y. Do the operation</div><div =
style>}</div><div style>=A0 =A0 =A0//Restore the state to x (or an equivale=
nt state x&#39;)</div>
<div>}</div><div><br><div class=3D"gmail_extra">An example:</div><div class=
=3D"gmail_extra" style>The example is a little long. But it explains the us=
e and power of mutable function nicely.</div><div class=3D"gmail_extra" sty=
le>
<br></div><div class=3D"gmail_extra">Consider a Linked list with 2 pointers=
 - one next pointer and one forward pointer - for each node. The forward po=
inter points to some arbitrary node ahead of it. The operation to be perfor=
med is clone.</div>
<div class=3D"gmail_extra"><br></div><div class=3D"gmail_extra" style>struc=
t Node {</div><div class=3D"gmail_extra" style>int num;</div><div class=3D"=
gmail_extra" style>Node *next, *forward;</div><div class=3D"gmail_extra" st=
yle>}</div>
<div class=3D"gmail_extra" style><br></div><div class=3D"gmail_extra" style=
>A sample list is shown below. The next pointers point like this.</div><div=
 class=3D"gmail_extra" style>10 -&gt; 20 -&gt; 30 -&gt; 40 -&gt; 50</div><d=
iv class=3D"gmail_extra" style>
The forward pointers point like this</div><div class=3D"gmail_extra" style>=
10 -&gt; 30 &amp; 20 -&gt; 50. All other forward pointers are nullptrs. 30&=
#39;s forward pointer cannot point to 20 as it is behind it.</div><div clas=
s=3D"gmail_extra" style>
<br></div><div class=3D"gmail_extra" style>There are 2 algorithms that can =
do it efficiently in O(n) time and O(1) space (There is an algorithm that d=
oes not modify the list even temporarily. But that uses O(n) time and O(n) =
space). But they modify the Linked list during cloning and restore it to th=
e original state in the end. I am giving only algorithm 1 for the sake of b=
revity. The pseudo code is given in the end.</div>
<div class=3D"gmail_extra" style><br></div><div class=3D"gmail_extra" style=
>In algorithm 1 next pointer is modified and restored to the original state=
 for cloning.</div><div class=3D"gmail_extra" style>In algorithm 2 forward =
pointer is modified and restored=A0to the original state=A0for cloning.</di=
v>
<div class=3D"gmail_extra" style><br></div><div class=3D"gmail_extra" style=
>It is clear that none of the pointers are mutable whereas the clone operat=
ion is mutable. The worse thing is the variable that is mutable depends on =
the algorithm chosen and not on the meaning of the class. Semantically this=
 is unacceptable. The mutable function provides the alternate.</div>
<div class=3D"gmail_extra" style><br></div><div class=3D"gmail_extra" style=
>In my proposal I erroneously mentioned that const_cast can be surreptitiou=
sly used for object modification. I stand corrected on this and thanks to=
=A0Martinho Fernandes for pointing it out.</div>
<div class=3D"gmail_extra" style><br></div><div class=3D"gmail_extra" style=
>//Pseudo code for algorithm 1.</div><div class=3D"gmail_extra" style>void =
LinkedList::CloneAlgo1() mutable {</div><div class=3D"gmail_extra" style>1.=
 In pass 1 duplicate the nodes and make the next pointers point to the dupl=
icate nodes</div>
<div class=3D"gmail_extra" style>The list becomes 10 -&gt; 10&#39; -&gt; 20=
 -&gt; 20&#39; -&gt; 30 -&gt; 30&#39; -&gt; 40 -&gt; 40&#39; -&gt; 50 -&gt;=
 50&#39;</div><div class=3D"gmail_extra" style>The forward pointers do not =
change. 10 -&gt; 30 &amp; 20 -&gt; 50</div>
<div class=3D"gmail_extra" style>2. pass 2=A0</div><div class=3D"gmail_extr=
a" style>if(even node&#39;s forward ptr !=3D nullptr)</div><div class=3D"gm=
ail_extra" style>=A0 =A0 =A0 =A0 =A0 evenNode-&gt;next-&gt;forwardPtr =3D e=
venNode-&gt;forwardPtr-&gt;next;</div>
<div class=3D"gmail_extra" style>The following forward pointers get added. =
10&#39; -&gt; 30&#39; &amp; 20&#39; -&gt; 50&#39;</div><div class=3D"gmail_=
extra" style>3. In pass 3 split the list into odd list and even list.</div>
<div class=3D"gmail_extra" style>And we cloned.</div><div class=3D"gmail_ex=
tra" style>}</div><div class=3D"gmail_extra"><br></div><div class=3D"gmail_=
extra" style>Hariharan S</div><div class=3D"gmail_extra" style><br></div><d=
iv class=3D"gmail_extra">
<div class=3D"gmail_quote">On Sat, Apr 27, 2013 at 9:01 PM, Martinho Fernan=
des <span dir=3D"ltr">&lt;<a href=3D"mailto:martinho.fernandes@gmail.com" t=
arget=3D"_blank">martinho.fernandes@gmail.com</a>&gt;</span> wrote:<br><blo=
ckquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left=
-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;paddi=
ng-left:1ex">
<div dir=3D"ltr"><div class=3D"im">On Sat, Apr 27, 2013 at 4:02 PM, Harihar=
an Subramanian <span dir=3D"ltr">&lt;<a href=3D"mailto:tohari@gmail.com" ta=
rget=3D"_blank">tohari@gmail.com</a>&gt;</span> wrote:<br><div class=3D"gma=
il_extra">
<div class=3D"gmail_quote">
<blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-=
left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;p=
adding-left:1ex">If there are lot of lazy member initializations then all t=
hose member variables need to be declared mutable and that makes the progra=
m error prone.<span><font color=3D"#888888"> <br>


</font></span></blockquote></div><br></div></div><div class=3D"gmail_extra"=
>If there are lots of lazy member initializations it is time to start seein=
g the pattern here and making a lazy_initialized template.<br></div></div>
<div class=3D""><div class=3D"h5">

<p></p>

-- <br>
=A0<br>
--- <br>
You received this message because you are subscribed to a topic in the Goog=
le Groups &quot;ISO C++ Standard - Future Proposals&quot; group.<br>
To unsubscribe from this topic, visit <a href=3D"https://groups.google.com/=
a/isocpp.org/d/topic/std-proposals/8TGpsfF5aXs/unsubscribe?hl=3Den" target=
=3D"_blank">https://groups.google.com/a/isocpp.org/d/topic/std-proposals/8T=
GpsfF5aXs/unsubscribe?hl=3Den</a>.<br>

To unsubscribe from this group and all its topics, send an email to <a href=
=3D"mailto:std-proposals%2Bunsubscribe@isocpp.org" target=3D"_blank">std-pr=
oposals+unsubscribe@isocpp.org</a>.<br>
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org" target=3D"_blank">std-proposals@isocpp.org</a>.<br>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/?hl=3Den" target=3D"_blank">http://groups.google.com/a/isocpp=
..org/group/std-proposals/?hl=3Den</a>.<br>
=A0<br>
=A0<br>
</div></div></blockquote></div><br></div></div></div>

<p></p>

-- <br />
&nbsp;<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/?hl=3Den">http://groups.google.com/a/isocpp.org/group/std-pro=
posals/?hl=3Den</a>.<br />
&nbsp;<br />
&nbsp;<br />

--001a11c26804f6d4bb04db5c84e0--

.


Author: Lawrence Crowl <crowl@googlers.com>
Date: Mon, 29 Apr 2013 11:41:34 -0700
Raw View
On 4/27/13, Hariharan Subramanian <tohari@gmail.com> wrote:
> A proposal to add mutable function and mutable code section
>
> *Problem:*
>
> class Member; //definition elsewhere
>
> class A
> {
> private:
> Member *member;
> //Other variables
> public:
> A() { member = nullptr; }
> const Member* A::GetMember() const;
> //Other functions
> };
>
> const Member* A::GetMember() const {
> if(member == nullptr) {
> //lazy initialize member
> }
> return member;
> }
>
> The above code results in compilation error as we modify a member
> variable within a const function.
>
> *Current solutions and their problems:*
>
> *Current Solution 1:*
> Make member variable mutable.
> *The problem with this solution:*
> This defeats the very purpose of having const member functions.
> Semantically it is a constant and other const functions should
> not modify it. Making it mutable gives any function the power to
> modify it. If there are lot of lazy member initializations then
> all those member variables need to be declared mutable and that
> makes the program error prone.
>
>
> *Current Solution 2:*
> Let the return value be const but the function be non-const. Hence
> the prototype becomes const Member* A::GetMember().
> *The problem with this solution:*
> Consider the code below.
> void foo(const A &obj) {
> const Member &m1 = obj.GetMember(); //Compilation error!
> }
> To avoid the above compilation error const_cast the 'obj' or
> pass A &obj instead of const A &obj. If we do a const_cast it
> would mean that all the functions that have const A& should do
> a const_cast to call GetMember. This results in a difficult to
> maintain code. The other alternative of passing A &obj postpones
> the problem to the callee of foo. Now that callee function has
> to make the same decision. This has the cascading effect.
>
> *Proposed solution:*
> We can see that none of the above solutions are desirable. We can
> introduce the concept of mutable function and mutable code section.
>
> *Solution using mutable code section:*
>
> const Member* A::GetMember() const {
> mutable {
> if(member == nullptr) {
> //lazy initialize member
> }
> }
> return member;
> }
>
> The above mutable code section tells the compiler to suspend
> checking if variables are modified or not.
>
> *Solution using mutable function:*
> Introduce a new private mutable member function
> LazyInitializeMember. The code will be changed like this.
>
> void A::LazyInitializeMember() mutable {
> //lazy intialize member
> }
>
> const Member* A::GetMember() const {
> LazyInitializeMember();
> return member;
> }
>
> Even const member functions and const variables can call a
> mutable function. A mutable function can call both const and
> non-const functions.
>
> The above two solutions capture the intent of the programmer "Even
> though this function modifies the member variable it is fine to
> treat it as a no modification". Mutable function/code section makes
> the code less error prone and easier to maintain. Mutable member
> variable has a different intent "This variable can be modified by
> any function without affecting const-ness". In fact mutable member
> variable and mutable function/code section are complementary.
>
> *Other points:*
> 1. Is there any real life use case for mutable public member
> functions?  They are as dangerous as mutable public member
> variables.

In C++, a const methods means "this operation will not change
the logical state of the object".  In the C++ standard library,
const also means "this operation is safe for concurrent reading,
i.e. will not make unprotected changes to the state".

These semantics are an essential part of an interface, so in contrast
to your proposal, I would make mutable part of the public interface
to distinguish the two cases above.

>
> 2a. Can we nest a mutable code section within a mutable code
> section even though it is redundant?

If mutable is part of the interface, then a mutable code section
becomes unnecessary.

>
> 2b. As we have mutable code section do we need to have const code
> section also? In a const code section we cannot modify a member
> variable with the exception of mutable member variable. We should
> also be able to nest a mutable code section within a const code
> section and vice versa. This can be taken to multiple levels.
> mutable {
> const {
> mutable {
> }
> }
> }
> Even though it might seem that we should allow 2a if we allow
> 2b it is not true. We can only disallow redundant code sections
> while allowing 2b.

Show me a use case where this extra nesting is helpful.

> 3. Do we have to specify what member variables are mutable in
> the mutable code section?
>
> mutable (member) {
> //Only 'member' can be modified. Other variables cannot be modified.
> }
> If we have const code section then it also should have this
> capability to specify.
>
> 4. Do we disallow or let the compiler generate a warning if
> we don't modify any member variable within a mutable code
> section/function. Point 3 should be taken into consideration
> for this.
>
> *Another example:*
> http://www.geeksforgeeks.org/a-linked-list-with-next-and-arbit-pointer/
> The link above has the problem definition (cloning a linked list)
> and 2 solutions. The first solution takes O(n) time and O(n)
> space. The second solution takes O(n) time and O(1) space. If
> cloning is implemented using the second solution the original
> linked list should be modified and restored. Mutable function/code
> section is apt for this. Otherwise we need to make the next
> pointer mutable which is incorrect or make the clone function
> non-const which is also incorrect.

--
Lawrence Crowl

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/?hl=en.



.