Topic: Move Semantics: Incomplete?


Author: josephlawrie1@gmail.com
Date: Sun, 12 Jan 2014 23:58:25 -0800 (PST)
Raw View
------=_Part_3156_28614119.1389599905540
Content-Type: text/plain; charset=UTF-8

Pretty much copied from my SO question:

Move semantics replace copy semantics in situations where copying is
inefficient. Copy semantics deals fully with copyable objects, including
const objects. Already, there exists a myriad of non-copyable objects in
c++11, for example std::unique_ptr. These objects rely on move semantics
completely because moving from an object allows for invalidating it. This
is important (imho) for popular design patterns like RAII.

A problem occurs when a const non-copyable object is assigned to an area of
memory. Such an object can't be recovered in any way. This is obviously
important during the lifetime of the object, because of its constness. At
the end of it's lifetime, when the destructor is called however, the
(non-existent) object is briefly non-const (well kinda, please read on).

I suggest that a *moving* destructor could be a valuable addition to the
move semantics model.

Consider a simple situation where an unique_ptr is used in an
unordered_set. You can insert into this set using a move constructor (or
construct "emplace"), however if you wanted to move this pointer to another
unordered_set (i.e. keeping it const) it would be impossible. Essentially,
there is a iterator insert((possibly const) key&&) but no const key&&
erase(iterator). In fact it would be impossible, since the key is const and
can't be moved from and if a const copy constructor was provided,
unique_ptr could be deleted multiple times with no compile error. The
container could only be extended to return some pointer to the key, and
then forget about it.

A moving destructor/constructor could solve this ie const MyClass&&
~MyClass() const,  The destructor doesn't have to modify anything, only
destroy the object as if it were no longer a valid handle to whatever
resource it controlled, and create a similar object i.e. explicity make a
non-temp behave as a temp would.

You could call it like const unique_ptr<MyClass> pointer(erase(iterator)); where
erase would return std::move(object) where object would normally be
deleted. Ideally this would be a separate function unordered_set::remove,
to avoid overload confusion.

To sum up

   - Allows move from const object at end of lifetime - a const move would
   not solve this because the moved-from object would get deleted unaware of
   it's evil twin
   - Only valid in a return statement i.e. intercepting an object at the
   end of it's lifetime - ensure no one tries to invalidate a constant
   mid-scope
   - Similar to if the object had been created with a destructor that moved
   some elements to a globally specified memory location ( i'm just saying
   similar can be done with hacks, not that this is a good solution

Also it solves the similar move destructor problem I've seen elsewhere
http://meetingcpp.com/index.php/br/items/c1y-move-copy-destructors.html
using the pattern;

   1. create object in desired memory location from existing object (in
   undesirable location)
   2. (the existing object is deleted using a destructor that knows it is
   no longer the owner)
   3. delete the new object (with standard destructor for memory location

Is this at all a sensible idea? Why/ why not?


--

---
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/.

------=_Part_3156_28614119.1389599905540
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">Pretty much copied from my SO question:<br><br><div class=
=3D"post-text" itemprop=3D"description">

        <p>Move semantics replace copy semantics in situations where=20
copying is inefficient. Copy semantics deals fully with copyable=20
objects, including const objects. Already, there exists a myriad of non-cop=
yable objects in c++11, for=20
example std::unique_ptr. These objects rely on move semantics completely
 because moving from an object allows for invalidating it. This is=20
important (imho) for popular design patterns like RAII.

</p><p>A problem occurs when a const non-copyable object is assigned to an=
=20
area of memory. Such an object can't be recovered in any way. This is obvio=
usly important during the lifetime of the object,=20
because of its constness. At the end of it's lifetime, when the=20
destructor is called however, the (non-existent) object is briefly=20
non-const (well kinda, please read on).=20

</p><p>I suggest that a <em>moving</em> destructor could be a valuable addi=
tion to the move semantics model.</p>

<p>Consider a simple situation where an unique_ptr is used in an unordered_=
set. You can <code>insert</code>
 into this set using a move constructor (or construct "emplace"),=20
however if you wanted to move this pointer to another unordered_set=20
(i.e. keeping it const) it would be impossible. Essentially, there is a <co=
de>iterator insert((possibly const) key&amp;&amp;)</code> but no <code>cons=
t key&amp;&amp; erase(iterator)</code>. In fact it would be impossible, sin=
ce the key is const and can't be moved from and if a const copy constructor=
 was provided, unique_ptr could be deleted multiple times with no compile e=
rror. The container could only be extended to return some pointer to the ke=
y, and then forget about it.

</p><p>A moving destructor/constructor could solve this ie <code>const MyCl=
ass&amp;&amp; ~MyClass() const</code>,&nbsp; The destructor doesn't have to=
 modify=20
anything, only destroy the object as if it were no longer a valid handle
 to whatever resource it controlled, and create a similar object i.e. expli=
city make a non-temp behave as a temp would.</p><p>You could call it like <=
span style=3D"font-family: courier new,monospace;">const unique_ptr&lt;MyCl=
ass&gt; pointer(erase(iterator)); </span>where <font face=3D"courier new,mo=
nospace">erase </font>would <font face=3D"courier new,monospace">return std=
::move(object) </font>where object would normally be deleted. Ideally this =
would be a separate function unordered_set::remove, to avoid overload confu=
sion.</p><p>To sum up</p><ul><li>Allows move from const object at end of li=
fetime - a const move would not solve this because the moved-from object wo=
uld get deleted unaware of it's evil twin</li><li>Only valid in a return st=
atement i.e. intercepting an object at the end of it's lifetime - ensure no=
 one tries to invalidate a constant mid-scope<br></li><li>Similar to if the=
 object had been created with a destructor that moved some elements to a gl=
obally specified memory location ( i'm just saying similar can be done with=
 hacks, not that this is a good solution</li></ul><p>Also it solves the sim=
ilar move destructor problem I've seen elsewhere http://meetingcpp.com/inde=
x.php/br/items/c1y-move-copy-destructors.html using the pattern;</p><ol><li=
>create object in desired memory location from existing object (in undesira=
ble location)</li><li>(the existing object is deleted using a destructor th=
at knows it is no longer the owner)</li><li>delete the new object (with sta=
ndard destructor for memory location</li></ol><p>Is this at all a sensible =
idea? Why/ why not?<br></p><p></p></div><br></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/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_3156_28614119.1389599905540--

.


Author: Miro Knejp <miro@knejp.de>
Date: Mon, 13 Jan 2014 11:43:09 +0100
Raw View
This is a multi-part message in MIME format.
--------------000309090800060903000406
Content-Type: text/plain; charset=UTF-8; format=flowed

I don't think move semantics is to blame here, but rather
(unordered_)set. Those containers have the invariant that elements do
not change after insertion. This is done to make sure the hash/order
remains the same and preserves uniqueness. So moving out elements is not
possible by design. This also means that with the current interface it's
impossible to retrieve a value with move-only type once inserted.
Technically the container is not necessarily implemented with "const"
internally, but the iterators return const references.

For the problem at hand there's no need for any fancy new destructor
magic, only a single-element "extract" method ("remove" is used in
<algorithm> for a different purpose, but bikeshed it) which returns the
removed value. This would work simply by moving the element to a
temporary before destroying it. The call line wouldn't differ much from
your "remove" example: "auto value = myset.extract(myiterator);". This
must be a method of the container as it currently cannot be implemented
using the public interface (at least not without const_cast but that may
break the container). Now assuming the move constructor is nothrow
everything is fine, but otherwise we're in a world of trouble for
ensuring the strong exception safety guarantee. Would probably have to
fallback to copy construction in that case, which wouldn't help the
noncopyable scenario.

Anyway, to sum up my point is that no change to the language is
required. Only the addition of an "erase and return" method to
containers where the contained elements are immutable.

P.S.: You almost certainly *never* want a function to return a "(const)
T&&", unless your name is std::move or std::forward. Just return "T" and
the move is implicit if returning a local variable. And excessively
labeling values (not references) with const in arguments or return types
may prevent implicit move-semantics so use it with care.

Am 13.01.2014 08:58, schrieb josephlawrie1@gmail.com:
> Pretty much copied from my SO question:
>
> Move semantics replace copy semantics in situations where copying is
> inefficient. Copy semantics deals fully with copyable objects,
> including const objects. Already, there exists a myriad of
> non-copyable objects in c++11, for example std::unique_ptr. These
> objects rely on move semantics completely because moving from an
> object allows for invalidating it. This is important (imho) for
> popular design patterns like RAII.
>
> A problem occurs when a const non-copyable object is assigned to an
> area of memory. Such an object can't be recovered in any way. This is
> obviously important during the lifetime of the object, because of its
> constness. At the end of it's lifetime, when the destructor is called
> however, the (non-existent) object is briefly non-const (well kinda,
> please read on).
>
> I suggest that a /moving/ destructor could be a valuable addition to
> the move semantics model.
>
> Consider a simple situation where an unique_ptr is used in an
> unordered_set. You can |insert| into this set using a move constructor
> (or construct "emplace"), however if you wanted to move this pointer
> to another unordered_set (i.e. keeping it const) it would be
> impossible. Essentially, there is a |iterator insert((possibly const)
> key&&)| but no |const key&& erase(iterator)|. In fact it would be
> impossible, since the key is const and can't be moved from and if a
> const copy constructor was provided, unique_ptr could be deleted
> multiple times with no compile error. The container could only be
> extended to return some pointer to the key, and then forget about it.
>
> A moving destructor/constructor could solve this ie |const MyClass&&
> ~MyClass() const|,  The destructor doesn't have to modify anything,
> only destroy the object as if it were no longer a valid handle to
> whatever resource it controlled, and create a similar object i.e.
> explicity make a non-temp behave as a temp would.
>
> You could call it like const unique_ptr<MyClass>
> pointer(erase(iterator)); where erase would return std::move(object)
> where object would normally be deleted. Ideally this would be a
> separate function unordered_set::remove, to avoid overload confusion.
>
> To sum up
>
>   * Allows move from const object at end of lifetime - a const move
>     would not solve this because the moved-from object would get
>     deleted unaware of it's evil twin
>   * Only valid in a return statement i.e. intercepting an object at
>     the end of it's lifetime - ensure no one tries to invalidate a
>     constant mid-scope
>   * Similar to if the object had been created with a destructor that
>     moved some elements to a globally specified memory location ( i'm
>     just saying similar can be done with hacks, not that this is a
>     good solution
>
> Also it solves the similar move destructor problem I've seen elsewhere
> http://meetingcpp.com/index.php/br/items/c1y-move-copy-destructors.html using
> the pattern;
>
>  1. create object in desired memory location from existing object (in
>     undesirable location)
>  2. (the existing object is deleted using a destructor that knows it
>     is no longer the owner)
>  3. delete the new object (with standard destructor for memory location
>
> Is this at all a sensible idea? Why/ why not?
>

--

---
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/.

--------------000309090800060903000406
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<html>
  <head>
    <meta content=3D"text/html; charset=3DUTF-8" http-equiv=3D"Content-Type=
">
  </head>
  <body text=3D"#000000" bgcolor=3D"#FFFFFF">
    I don't think move semantics is to blame here, but rather
    (unordered_)set. Those containers have the invariant that elements
    do not change after insertion. This is done to make sure the
    hash/order remains the same and preserves uniqueness. So moving out
    elements is not possible by design. This also means that with the
    current interface it's impossible to retrieve a value with move-only
    type once inserted. Technically the container is not necessarily
    implemented with "const" internally, but the iterators return const
    references.<br>
    <br>
    For the problem at hand there's no need for any fancy new destructor
    magic, only a single-element "extract" method ("remove" is used in
    &lt;algorithm&gt; for a different purpose, but bikeshed it) which
    returns the removed value. This would work simply by moving the
    element to a temporary before destroying it. The call line wouldn't
    differ much from your "remove" example: "auto value =3D
    myset.extract(myiterator);". This must be a method of the container
    as it currently cannot be implemented using the public interface (at
    least not without const_cast but that may break the container). Now
    assuming the move constructor is nothrow everything is fine, but
    otherwise we're in a world of trouble for ensuring the strong
    exception safety guarantee. Would probably have to fallback to copy
    construction in that case, which wouldn't help the noncopyable
    scenario.<br>
    <br>
    Anyway, to sum up my point is that no change to the language is
    required. Only the addition of an "erase and return" method to
    containers where the contained elements are immutable.<br>
    <br>
    P.S.: You almost certainly *never* want a function to return a
    "(const) T&amp;&amp;", unless your name is std::move or
    std::forward. Just return "T" and the move is implicit if returning
    a local variable. And excessively labeling values (not references)
    with const in arguments or return types may prevent implicit
    move-semantics so use it with care.<br>
    <br>
    <div class=3D"moz-cite-prefix">Am 13.01.2014 08:58, schrieb
      <a class=3D"moz-txt-link-abbreviated" href=3D"mailto:josephlawrie1@gm=
ail.com">josephlawrie1@gmail.com</a>:<br>
    </div>
    <blockquote
      cite=3D"mid:836fd532-bb49-4402-a63c-68b72ccbc06d@isocpp.org"
      type=3D"cite">
      <div dir=3D"ltr">Pretty much copied from my SO question:<br>
        <br>
        <div class=3D"post-text" itemprop=3D"description">
          <p>Move semantics replace copy semantics in situations where
            copying is inefficient. Copy semantics deals fully with
            copyable objects, including const objects. Already, there
            exists a myriad of non-copyable objects in c++11, for
            example std::unique_ptr. These objects rely on move
            semantics completely because moving from an object allows
            for invalidating it. This is important (imho) for popular
            design patterns like RAII.
          </p>
          <p>A problem occurs when a const non-copyable object is
            assigned to an area of memory. Such an object can't be
            recovered in any way. This is obviously important during the
            lifetime of the object, because of its constness. At the end
            of it's lifetime, when the destructor is called however, the
            (non-existent) object is briefly non-const (well kinda,
            please read on). </p>
          <p>I suggest that a <em>moving</em> destructor could be a
            valuable addition to the move semantics model.</p>
          <p>Consider a simple situation where an unique_ptr is used in
            an unordered_set. You can <code>insert</code> into this set
            using a move constructor (or construct "emplace"), however
            if you wanted to move this pointer to another unordered_set
            (i.e. keeping it const) it would be impossible. Essentially,
            there is a <code>iterator insert((possibly const)
              key&amp;&amp;)</code> but no <code>const key&amp;&amp;
              erase(iterator)</code>. In fact it would be impossible,
            since the key is const and can't be moved from and if a
            const copy constructor was provided, unique_ptr could be
            deleted multiple times with no compile error. The container
            could only be extended to return some pointer to the key,
            and then forget about it.
          </p>
          <p>A moving destructor/constructor could solve this ie <code>cons=
t
              MyClass&amp;&amp; ~MyClass() const</code>,=C2=A0 The destruct=
or
            doesn't have to modify anything, only destroy the object as
            if it were no longer a valid handle to whatever resource it
            controlled, and create a similar object i.e. explicity make
            a non-temp behave as a temp would.</p>
          <p>You could call it like <span style=3D"font-family: courier
              new,monospace;">const unique_ptr&lt;MyClass&gt;
              pointer(erase(iterator)); </span>where <font
              face=3D"courier new,monospace">erase </font>would <font
              face=3D"courier new,monospace">return std::move(object) </fon=
t>where
            object would normally be deleted. Ideally this would be a
            separate function unordered_set::remove, to avoid overload
            confusion.</p>
          <p>To sum up</p>
          <ul>
            <li>Allows move from const object at end of lifetime - a
              const move would not solve this because the moved-from
              object would get deleted unaware of it's evil twin</li>
            <li>Only valid in a return statement i.e. intercepting an
              object at the end of it's lifetime - ensure no one tries
              to invalidate a constant mid-scope<br>
            </li>
            <li>Similar to if the object had been created with a
              destructor that moved some elements to a globally
              specified memory location ( i'm just saying similar can be
              done with hacks, not that this is a good solution</li>
          </ul>
          <p>Also it solves the similar move destructor problem I've
            seen elsewhere
            <a class=3D"moz-txt-link-freetext" href=3D"http://meetingcpp.co=
m/index.php/br/items/c1y-move-copy-destructors.html">http://meetingcpp.com/=
index.php/br/items/c1y-move-copy-destructors.html</a>
            using the pattern;</p>
          <ol>
            <li>create object in desired memory location from existing
              object (in undesirable location)</li>
            <li>(the existing object is deleted using a destructor that
              knows it is no longer the owner)</li>
            <li>delete the new object (with standard destructor for
              memory location</li>
          </ol>
          <p>Is this at all a sensible idea? Why/ why not?<br>
          </p>
        </div>
      </div>
    </blockquote>
    <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 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/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

--------------000309090800060903000406--


.


Author: josephlawrie1@gmail.com
Date: Mon, 13 Jan 2014 03:58:10 -0800 (PST)
Raw View
------=_Part_2638_4756528.1389614290170
Content-Type: text/plain; charset=UTF-8

Yeah this was pretty much my initial conclusion too. I thought this
destructor might be useful in other situations as well. It is really more a
constructor. I know it is a very elaborate solution to a simple problem, I
was just curious of other peoples' opinions. It seems weird that making an
object const means that it and only it owns that resource. If that's the
way its got to be, so be it. Unfortunately, any innocent const t =
std::move(getUncopyableType) is a dead end, even if we intended to move it
somewhere else later. (I know strictly speaking, that's what const should
do, but I feel end-of-lifetime is a good chance to avoid it - a non RAII
object like const int could be moved, right?)

Thank you for a sensible answer, elsewhere it seems this kind of question
attracts "you're an idiot, don't put unique_ptr in a set". (i was using the
destructor's signature to convey my meaning, not necessarily as an actual
implementation thing)

And I've been in favour of an extract method for a long time...

On Monday, 13 January 2014 21:13:09 UTC+10:30, Miro Knejp wrote:
>
>  I don't think move semantics is to blame here, but rather
> (unordered_)set. Those containers have the invariant that elements do not
> change after insertion. This is done to make sure the hash/order remains
> the same and preserves uniqueness. So moving out elements is not possible
> by design. This also means that with the current interface it's impossible
> to retrieve a value with move-only type once inserted. Technically the
> container is not necessarily implemented with "const" internally, but the
> iterators return const references.
>
> For the problem at hand there's no need for any fancy new destructor
> magic, only a single-element "extract" method ("remove" is used in
> <algorithm> for a different purpose, but bikeshed it) which returns the
> removed value. This would work simply by moving the element to a temporary
> before destroying it. The call line wouldn't differ much from your "remove"
> example: "auto value = myset.extract(myiterator);". This must be a method
> of the container as it currently cannot be implemented using the public
> interface (at least not without const_cast but that may break the
> container). Now assuming the move constructor is nothrow everything is
> fine, but otherwise we're in a world of trouble for ensuring the strong
> exception safety guarantee. Would probably have to fallback to copy
> construction in that case, which wouldn't help the noncopyable scenario.
>
> Anyway, to sum up my point is that no change to the language is required.
> Only the addition of an "erase and return" method to containers where the
> contained elements are immutable.
>
> P.S.: You almost certainly *never* want a function to return a "(const)
> T&&", unless your name is std::move or std::forward. Just return "T" and
> the move is implicit if returning a local variable. And excessively
> labeling values (not references) with const in arguments or return types
> may prevent implicit move-semantics so use it with care.
>
> Am 13.01.2014 08:58, schrieb joseph...@gmail.com <javascript:>:
>
> Pretty much copied from my SO question:
>
>  Move semantics replace copy semantics in situations where copying is
> inefficient. Copy semantics deals fully with copyable objects, including
> const objects. Already, there exists a myriad of non-copyable objects in
> c++11, for example std::unique_ptr. These objects rely on move semantics
> completely because moving from an object allows for invalidating it. This
> is important (imho) for popular design patterns like RAII.
>
> A problem occurs when a const non-copyable object is assigned to an area
> of memory. Such an object can't be recovered in any way. This is obviously
> important during the lifetime of the object, because of its constness. At
> the end of it's lifetime, when the destructor is called however, the
> (non-existent) object is briefly non-const (well kinda, please read on).
>
> I suggest that a *moving* destructor could be a valuable addition to the
> move semantics model.
>
> Consider a simple situation where an unique_ptr is used in an
> unordered_set. You can insert into this set using a move constructor (or
> construct "emplace"), however if you wanted to move this pointer to another
> unordered_set (i.e. keeping it const) it would be impossible. Essentially,
> there is a iterator insert((possibly const) key&&) but no const key&&
> erase(iterator). In fact it would be impossible, since the key is const
> and can't be moved from and if a const copy constructor was provided,
> unique_ptr could be deleted multiple times with no compile error. The
> container could only be extended to return some pointer to the key, and
> then forget about it.
>
> A moving destructor/constructor could solve this ie const MyClass&&
> ~MyClass() const,  The destructor doesn't have to modify anything, only
> destroy the object as if it were no longer a valid handle to whatever
> resource it controlled, and create a similar object i.e. explicity make a
> non-temp behave as a temp would.
>
> You could call it like const unique_ptr<MyClass>
> pointer(erase(iterator)); where erase would return std::move(object) where
> object would normally be deleted. Ideally this would be a separate function
> unordered_set::remove, to avoid overload confusion.
>
> To sum up
>
>    - Allows move from const object at end of lifetime - a const move
>    would not solve this because the moved-from object would get deleted
>    unaware of it's evil twin
>    - Only valid in a return statement i.e. intercepting an object at the
>    end of it's lifetime - ensure no one tries to invalidate a constant
>    mid-scope
>     - Similar to if the object had been created with a destructor that
>    moved some elements to a globally specified memory location ( i'm just
>    saying similar can be done with hacks, not that this is a good solution
>
> Also it solves the similar move destructor problem I've seen elsewhere
> http://meetingcpp.com/index.php/br/items/c1y-move-copy-destructors.htmlusing the pattern;
>
>    1. create object in desired memory location from existing object (in
>    undesirable location)
>    2. (the existing object is deleted using a destructor that knows it is
>    no longer the owner)
>    3. delete the new object (with standard destructor for memory location
>
> Is this at all a sensible idea? Why/ why not?
>
>
>

--

---
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/.

------=_Part_2638_4756528.1389614290170
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">Yeah this was pretty much my initial conclusion too. I tho=
ught this destructor might be useful in other situations as well. It is rea=
lly more a constructor. I know it is a very elaborate solution to a simple =
problem, I was just curious of other peoples' opinions. It seems weird that=
 making an object const means that it and only it owns that resource. If th=
at's the way its got to be, so be it. Unfortunately, any innocent const t =
=3D std::move(getUncopyableType) is a dead end, even if we intended to move=
 it somewhere else later. (I know strictly speaking, that's what const shou=
ld do, but I feel end-of-lifetime is a good chance to avoid it - a non RAII=
 object like const int could be moved, right?)<br><br>Thank you for a sensi=
ble answer, elsewhere it seems this kind of question attracts "you're an id=
iot, don't put unique_ptr in a set". (i was using the destructor's signatur=
e to convey my meaning, not necessarily as an actual implementation thing)<=
br><br>And I've been in favour of an extract method for a long time...<br><=
br>On Monday, 13 January 2014 21:13:09 UTC+10:30, Miro Knejp  wrote:<blockq=
uote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-lef=
t: 1px #ccc solid;padding-left: 1ex;">
 =20
   =20
 =20
  <div text=3D"#000000" bgcolor=3D"#FFFFFF">
    I don't think move semantics is to blame here, but rather
    (unordered_)set. Those containers have the invariant that elements
    do not change after insertion. This is done to make sure the
    hash/order remains the same and preserves uniqueness. So moving out
    elements is not possible by design. This also means that with the
    current interface it's impossible to retrieve a value with move-only
    type once inserted. Technically the container is not necessarily
    implemented with "const" internally, but the iterators return const
    references.<br>
    <br>
    For the problem at hand there's no need for any fancy new destructor
    magic, only a single-element "extract" method ("remove" is used in
    &lt;algorithm&gt; for a different purpose, but bikeshed it) which
    returns the removed value. This would work simply by moving the
    element to a temporary before destroying it. The call line wouldn't
    differ much from your "remove" example: "auto value =3D
    myset.extract(myiterator);". This must be a method of the container
    as it currently cannot be implemented using the public interface (at
    least not without const_cast but that may break the container). Now
    assuming the move constructor is nothrow everything is fine, but
    otherwise we're in a world of trouble for ensuring the strong
    exception safety guarantee. Would probably have to fallback to copy
    construction in that case, which wouldn't help the noncopyable
    scenario.<br>
    <br>
    Anyway, to sum up my point is that no change to the language is
    required. Only the addition of an "erase and return" method to
    containers where the contained elements are immutable.<br>
    <br>
    P.S.: You almost certainly *never* want a function to return a
    "(const) T&amp;&amp;", unless your name is std::move or
    std::forward. Just return "T" and the move is implicit if returning
    a local variable. And excessively labeling values (not references)
    with const in arguments or return types may prevent implicit
    move-semantics so use it with care.<br>
    <br>
    <div>Am 13.01.2014 08:58, schrieb
      <a href=3D"javascript:" target=3D"_blank" gdf-obfuscated-mailto=3D"6c=
KnWkdAVEsJ" onmousedown=3D"this.href=3D'javascript:';return true;" onclick=
=3D"this.href=3D'javascript:';return true;">joseph...@gmail.com</a>:<br>
    </div>
    <blockquote type=3D"cite">
      <div dir=3D"ltr">Pretty much copied from my SO question:<br>
        <br>
        <div>
          <p>Move semantics replace copy semantics in situations where
            copying is inefficient. Copy semantics deals fully with
            copyable objects, including const objects. Already, there
            exists a myriad of non-copyable objects in c++11, for
            example std::unique_ptr. These objects rely on move
            semantics completely because moving from an object allows
            for invalidating it. This is important (imho) for popular
            design patterns like RAII.
          </p>
          <p>A problem occurs when a const non-copyable object is
            assigned to an area of memory. Such an object can't be
            recovered in any way. This is obviously important during the
            lifetime of the object, because of its constness. At the end
            of it's lifetime, when the destructor is called however, the
            (non-existent) object is briefly non-const (well kinda,
            please read on). </p>
          <p>I suggest that a <i>moving</i> destructor could be a
            valuable addition to the move semantics model.</p>
          <p>Consider a simple situation where an unique_ptr is used in
            an unordered_set. You can <code>insert</code> into this set
            using a move constructor (or construct "emplace"), however
            if you wanted to move this pointer to another unordered_set
            (i.e. keeping it const) it would be impossible. Essentially,
            there is a <code>iterator insert((possibly const)
              key&amp;&amp;)</code> but no <code>const key&amp;&amp;
              erase(iterator)</code>. In fact it would be impossible,
            since the key is const and can't be moved from and if a
            const copy constructor was provided, unique_ptr could be
            deleted multiple times with no compile error. The container
            could only be extended to return some pointer to the key,
            and then forget about it.
          </p>
          <p>A moving destructor/constructor could solve this ie <code>cons=
t
              MyClass&amp;&amp; ~MyClass() const</code>,&nbsp; The destruct=
or
            doesn't have to modify anything, only destroy the object as
            if it were no longer a valid handle to whatever resource it
            controlled, and create a similar object i.e. explicity make
            a non-temp behave as a temp would.</p>
          <p>You could call it like <span style=3D"font-family:courier new,=
monospace">const unique_ptr&lt;MyClass&gt;
              pointer(erase(iterator)); </span>where <font face=3D"courier =
new,monospace">erase </font>would <font face=3D"courier new,monospace">retu=
rn std::move(object) </font>where
            object would normally be deleted. Ideally this would be a
            separate function unordered_set::remove, to avoid overload
            confusion.</p>
          <p>To sum up</p>
          <ul>
            <li>Allows move from const object at end of lifetime - a
              const move would not solve this because the moved-from
              object would get deleted unaware of it's evil twin</li>
            <li>Only valid in a return statement i.e. intercepting an
              object at the end of it's lifetime - ensure no one tries
              to invalidate a constant mid-scope<br>
            </li>
            <li>Similar to if the object had been created with a
              destructor that moved some elements to a globally
              specified memory location ( i'm just saying similar can be
              done with hacks, not that this is a good solution</li>
          </ul>
          <p>Also it solves the similar move destructor problem I've
            seen elsewhere
            <a href=3D"http://meetingcpp.com/index.php/br/items/c1y-move-co=
py-destructors.html" target=3D"_blank" onmousedown=3D"this.href=3D'http://w=
ww.google.com/url?q\75http%3A%2F%2Fmeetingcpp.com%2Findex.php%2Fbr%2Fitems%=
2Fc1y-move-copy-destructors.html\46sa\75D\46sntz\0751\46usg\75AFQjCNFRJ17PX=
fUKoFXibyB5tZXRt46txg';return true;" onclick=3D"this.href=3D'http://www.goo=
gle.com/url?q\75http%3A%2F%2Fmeetingcpp.com%2Findex.php%2Fbr%2Fitems%2Fc1y-=
move-copy-destructors.html\46sa\75D\46sntz\0751\46usg\75AFQjCNFRJ17PXfUKoFX=
ibyB5tZXRt46txg';return true;">http://meetingcpp.com/index.<wbr>php/br/item=
s/c1y-move-copy-<wbr>destructors.html</a>
            using the pattern;</p>
          <ol>
            <li>create object in desired memory location from existing
              object (in undesirable location)</li>
            <li>(the existing object is deleted using a destructor that
              knows it is no longer the owner)</li>
            <li>delete the new object (with standard destructor for
              memory location</li>
          </ol>
          <p>Is this at all a sensible idea? Why/ why not?<br>
          </p>
        </div>
      </div>
    </blockquote>
    <br>
  </div>

</blockquote></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/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_2638_4756528.1389614290170--

.


Author: Miro Knejp <miro@knejp.de>
Date: Mon, 13 Jan 2014 14:04:32 +0100
Raw View
> Yeah this was pretty much my initial conclusion too. I thought this
> destructor might be useful in other situations as well. It is really
> more a constructor. I know it is a very elaborate solution to a simple
> problem, I was just curious of other peoples' opinions. It seems weird
> that making an object const means that it and only it owns that
> resource. If that's the way its got to be, so be it. Unfortunately,
> any innocent const t = std::move(getUncopyableType) is a dead end,
> even if we intended to move it somewhere else later. (I know strictly
> speaking, that's what const should do, but I feel end-of-lifetime is a
> good chance to avoid it - a non RAII object like const int could be
> moved, right?)
>
Well, sorry to say that, but just "don't do it". By marking a variable
as "const" you make the proimse "I shall not modify this value" and
therefore follows "I shall not move from this value". Strictly speaking
you cannot move from a "const int" either. Technically the compiler
calls int's copy constructor (which happens to perform the same
operation) as it does for any other type. I can only come up with three
use cases where marking a value (again, non-reference) as "const" make
sense:
1. You deliberately want to enforce copy semantics
2. You know the const overload of a method is more efficient
3. You want to get compile errors *if* you modify it by accident

const is in no way tied to the lifetime of an object or it's associated
resource. The object itself always owns the resource and some refer to
this kind of type as a "handle". Making the handle const means "I will
not change which resource this handle owns". Only one instance of
unique_ptr can own an object (unless something went horribly wrong).
Whether the unique_ptr itself is const or not has absolutely no impact
on this guarantee. The const modifier is a promise you make to the
compiler (which can be broken with const_cast, but never admit it exists).

So, basically, don't do
     const T t = std::move(getUncopyableType)
but instead
     auto t = std::move(getUncopyableType)
then you can keep on moving from t, and therefore (in your initial
example) move the unique_ptr into the new destination unordered_set (and
it's less typing, too). Local const values should ring a bell in code
reviews exactly for the reason that they prohibit move semantics.

I suggest Scott Meyer's talk from GoingNative 2013 where he elaborates
this copy/move topic and how const relates to it in more detail:
http://channel9.msdn.com/Events/GoingNative/2013/An-Effective-Cpp11-14-Sampler


--

---
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/.

.


Author: Evgeny Panasyuk <evgeny.panasyuk@gmail.com>
Date: Mon, 13 Jan 2014 06:20:22 -0800 (PST)
Raw View
------=_Part_1396_10135239.1389622822420
Content-Type: text/plain; charset=KOI8-R
Content-Transfer-Encoding: quoted-printable

13 J 2014 =C7., 11:58:25 UTC+4 joseph...@gmail.com :

> I suggest that a *moving* destructor could be a valuable addition to the=
=20
> move semantics model.
>
Alexander Stepanov mentioned something similar in his Notes on Programming:

"it is not really desirable to do that since there will be an extra=20
expensive copy done when the result is returned. It would be terribly nice=
=20
if we can assure that instead of an unnecessary copy, the compiler would do=
=20
an raw move and then not apply the destructor. In other words, we need what=
=20
I call a copy-destructor which is called whenever a copy is immediately=20
followed by the destructor. A copy destructor should default to move_raw."
http://www.stepanovpapers.com/notes.pdf

AFAIK, such kind of destructive move semantic was considered for C++11, but=
=20
rejected.

--=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/.

------=_Part_1396_10135239.1389622822420
Content-Type: text/html; charset=KOI8-R
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">13 J 2014&nbsp;=C7., 11:58:25 UTC+4 joseph...@gmail.com :<=
br><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;=
border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><p>I =
suggest that a <i>moving</i> destructor could be a valuable addition to the=
 move semantics model.</p></div></div></blockquote><div>Alexander Stepanov =
mentioned something similar in his Notes on Programming:<br><br>"it is not =
really desirable to do that since there will be an extra expensive copy don=
e when the result is returned. It would be terribly nice if we can assure t=
hat instead of an unnecessary copy, the compiler would do an raw move and t=
hen not apply the destructor. In other words, we need what I call a copy-de=
structor which is called whenever a copy is immediately followed by the des=
tructor. A copy destructor should default to move_raw."<br>http://www.stepa=
novpapers.com/notes.pdf<br><br>AFAIK, such kind of destructive move semanti=
c was considered for C++11, but rejected.<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/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_1396_10135239.1389622822420--

.


Author: Mikhail Semenov <mikhailsemenov1957@gmail.com>
Date: Mon, 13 Jan 2014 06:31:30 -0800 (PST)
Raw View
------=_Part_91_25301589.1389623490884
Content-Type: text/plain; charset=ISO-8859-1



>  Alexander Stepanov mentioned something similar in his Notes on
> Programming:
>
> "it is not really desirable to do that since there will be an extra
> expensive copy done when the result is returned. It would be terribly nice
> if we can assure that instead of an unnecessary copy, the compiler would do
> an raw move and then not apply the destructor. In other words, we need what
> I call a copy-destructor which is called whenever a copy is immediately
> followed by the destructor. A copy destructor should default to move_raw."
> http://www.stepanovpapers.com/notes.pdf
>
> AFAIK, such kind of destructive move semantic was considered for C++11,
> but rejected.
>

Isn't that what *copy/move elision* is for?


--

---
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/.

------=_Part_91_25301589.1389623490884
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><BR>
<BLOCKQUOTE style=3D"BORDER-LEFT: #ccc 1px solid; MARGIN: 0px 0px 0px 0.8ex=
; PADDING-LEFT: 1ex" class=3Dgmail_quote>
<DIV dir=3Dltr>
<DIV>Alexander Stepanov mentioned something similar in his Notes on Program=
ming:<BR><BR>"it is not really desirable to do that since there will be an =
extra expensive copy done when the result is returned. It would be terribly=
 nice if we can assure that instead of an unnecessary copy, the compiler wo=
uld do an raw move and then not apply the destructor. In other words, we ne=
ed what I call a copy-destructor which is called whenever a copy is immedia=
tely followed by the destructor. A copy destructor should default to move_r=
aw."<BR><A onmousedown=3D"this.href=3D'http://www.google.com/url?q\75http%3=
A%2F%2Fwww.stepanovpapers.com%2Fnotes.pdf\46sa\75D\46sntz\0751\46usg\75AFQj=
CNE787les7WbKSrVXpVHeexxAr7J0Q';return true;" onclick=3D"this.href=3D'http:=
//www.google.com/url?q\75http%3A%2F%2Fwww.stepanovpapers.com%2Fnotes.pdf\46=
sa\75D\46sntz\0751\46usg\75AFQjCNE787les7WbKSrVXpVHeexxAr7J0Q';return true;=
" href=3D"http://www.stepanovpapers.com/notes.pdf" target=3D_blank>http://w=
ww.stepanovpapers.com/<WBR>notes.pdf</A><BR><BR>AFAIK, such kind of destruc=
tive move semantic was considered for C++11, but rejected.<BR></DIV></DIV><=
/BLOCKQUOTE>
<DIV>&nbsp;</DIV>
<DIV>Isn't that what <STRONG>copy/move elision</STRONG> is for?</DIV>
<DIV>&nbsp;</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/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_91_25301589.1389623490884--

.


Author: Evgeny Panasyuk <evgeny.panasyuk@gmail.com>
Date: Mon, 13 Jan 2014 18:39:16 +0400
Raw View
13.01.2014 18:31, Mikhail Semenov:
> Isn't that what *copy/move elision* is for?

While use cases overlap, I think it is different concept. C++11 does not
have guarantee for move/copy elision (I heard that future versions will
have such guarantee).
copy/move destructor performs move and discards original destructor
(unlike C++11 move constructor).

--
Evgeny Panasyuk

--

---
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/.

.


Author: Howard Hinnant <howard.hinnant@gmail.com>
Date: Mon, 13 Jan 2014 12:32:06 -0500
Raw View
On Jan 13, 2014, at 6:58 AM, josephlawrie1@gmail.com wrote:

> elsewhere it seems this kind of question attracts "you're an idiot, don't put unique_ptr in a set". (i was using the destructor's signature to convey my meaning, not necessarily as an actual implementation thing)

Fwiw, I've put a reasonable answer on your SO post, and upvoted your question.  You are not an idiot. :-)

Howard

--

---
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/.

.


Author: Ville Voutilainen <ville.voutilainen@gmail.com>
Date: Mon, 13 Jan 2014 19:51:03 +0200
Raw View
On 13 January 2014 19:32, Howard Hinnant <howard.hinnant@gmail.com> wrote:
> On Jan 13, 2014, at 6:58 AM, josephlawrie1@gmail.com wrote:
>
>> elsewhere it seems this kind of question attracts "you're an idiot, don't put unique_ptr in a set". (i was using the destructor's signature to convey my meaning, not necessarily as an actual implementation thing)
>
> Fwiw, I've put a reasonable answer on your SO post, and upvoted your question.  You are not an idiot. :-)


I certainly am, because I don't immediately find a link to the related
SO discussion
in this thread. :P

--

---
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/.

.


Author: Howard Hinnant <howard.hinnant@gmail.com>
Date: Mon, 13 Jan 2014 12:53:58 -0500
Raw View
On Jan 13, 2014, at 12:51 PM, Ville Voutilainen <ville.voutilainen@gmail.com> wrote:

> On 13 January 2014 19:32, Howard Hinnant <howard.hinnant@gmail.com> wrote:
>> On Jan 13, 2014, at 6:58 AM, josephlawrie1@gmail.com wrote:
>>
>>> elsewhere it seems this kind of question attracts "you're an idiot, don't put unique_ptr in a set". (i was using the destructor's signature to convey my meaning, not necessarily as an actual implementation thing)
>>
>> Fwiw, I've put a reasonable answer on your SO post, and upvoted your question.  You are not an idiot. :-)
>
>
> I certainly am, because I don't immediately find a link to the related
> SO discussion
> in this thread. :P

Here you go.  I should've included it:

http://stackoverflow.com/q/21085735/576911

Howard

--

---
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/.

.


Author: Zhihao Yuan <zy@miator.net>
Date: Mon, 13 Jan 2014 13:57:46 -0500
Raw View
On Mon, Jan 13, 2014 at 12:32 PM, Howard Hinnant
<howard.hinnant@gmail.com> wrote:
>> elsewhere it seems this kind of question attracts "you're an idiot, don't put unique_ptr in a set". (i was using the destructor's signature to convey my meaning, not necessarily as an actual implementation thing)
>
> Fwiw, I've put a reasonable answer on your SO post, and upvoted your question.  You are not an idiot. :-)

I have a related need -- I want to pop an item out from queue, stack, or
priority_queue.  Obviously there are some "post actions" needed here, hope
an move dtor can help this.

--
Zhihao Yuan, ID lichray
The best way to predict the future is to invent it.
___________________________________________________
4BSD -- http://4bsd.biz/

--

---
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/.

.


Author: josephlawrie1@gmail.com
Date: Mon, 13 Jan 2014 16:53:10 -0800 (PST)
Raw View
------=_Part_57_25221191.1389660790820
Content-Type: text/plain; charset=UTF-8

That kind of behaviour follows from a strict definition of const, and I
have no problem with it. But I wasn't suggestng that the programmer just
decides t is const. If t were const (beyond control of the progammer, or
maybe for a really good reason) than any attempt to copy or move from it
results in the destructor being called twice. Essentially, c++ struggles to
deal with the notion of a unique object (no copy constructors) which
shouldn't me modified. Many people, like yourself, rightly say const
*should* make this impossible.

Also in the example, there is no interface to move from the container,
which seems silly to be honest. I'm amazed everyone just says "N3645<http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3645.pdf>/etc will never happen". You can't use c++11's flagship smart pointer in a
hash table without losing them. I think perl can do that...

On Monday, 13 January 2014 23:34:32 UTC+10:30, Miro Knejp wrote:
>
>
> > Yeah this was pretty much my initial conclusion too. I thought this
> > destructor might be useful in other situations as well. It is really
> > more a constructor. I know it is a very elaborate solution to a simple
> > problem, I was just curious of other peoples' opinions. It seems weird
> > that making an object const means that it and only it owns that
> > resource. If that's the way its got to be, so be it. Unfortunately,
> > any innocent const t = std::move(getUncopyableType) is a dead end,
> > even if we intended to move it somewhere else later. (I know strictly
> > speaking, that's what const should do, but I feel end-of-lifetime is a
> > good chance to avoid it - a non RAII object like const int could be
> > moved, right?)
> >
> Well, sorry to say that, but just "don't do it". By marking a variable
> as "const" you make the proimse "I shall not modify this value" and
> therefore follows "I shall not move from this value". Strictly speaking
> you cannot move from a "const int" either. Technically the compiler
> calls int's copy constructor (which happens to perform the same
> operation) as it does for any other type. I can only come up with three
> use cases where marking a value (again, non-reference) as "const" make
> sense:
> 1. You deliberately want to enforce copy semantics
> 2. You know the const overload of a method is more efficient
> 3. You want to get compile errors *if* you modify it by accident
>
> const is in no way tied to the lifetime of an object or it's associated
> resource. The object itself always owns the resource and some refer to
> this kind of type as a "handle". Making the handle const means "I will
> not change which resource this handle owns". Only one instance of
> unique_ptr can own an object (unless something went horribly wrong).
> Whether the unique_ptr itself is const or not has absolutely no impact
> on this guarantee. The const modifier is a promise you make to the
> compiler (which can be broken with const_cast, but never admit it exists).
>
> So, basically, don't do
>      const T t = std::move(getUncopyableType)
> but instead
>      auto t = std::move(getUncopyableType)
> then you can keep on moving from t, and therefore (in your initial
> example) move the unique_ptr into the new destination unordered_set (and
> it's less typing, too). Local const values should ring a bell in code
> reviews exactly for the reason that they prohibit move semantics.
>
> I suggest Scott Meyer's talk from GoingNative 2013 where he elaborates
> this copy/move topic and how const relates to it in more detail:
>
> http://channel9.msdn.com/Events/GoingNative/2013/An-Effective-Cpp11-14-Sampler
>
>
>

--

---
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/.

------=_Part_57_25221191.1389660790820
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">That kind of behaviour follows from a strict definition of=
 const, and I have no problem with it. But I wasn't suggestng that the prog=
rammer just decides t is const. If t were const (beyond control of the prog=
ammer, or maybe for a really good reason) than any attempt to copy or move =
from it results in the destructor being called twice. Essentially, c++ stru=
ggles to deal with the notion of a unique object (no copy constructors) whi=
ch shouldn't me modified. Many people, like yourself, rightly say const <i>=
should</i> make this impossible.<br><br>Also in the example, there is no in=
terface to move from the container, which seems silly to be honest. I'm ama=
zed everyone just says "<a href=3D"http://www.open-std.org/jtc1/sc22/wg21/d=
ocs/papers/2013/n3645.pdf" rel=3D"nofollow">N3645</a> /etc will never happe=
n". You can't use c++11's flagship smart pointer in a hash table without lo=
sing them. I think perl can do that...<br><br>On Monday, 13 January 2014 23=
:34:32 UTC+10:30, Miro Knejp  wrote:<blockquote class=3D"gmail_quote" style=
=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: =
1ex;">
<br>&gt; Yeah this was pretty much my initial conclusion too. I thought thi=
s=20
<br>&gt; destructor might be useful in other situations as well. It is real=
ly=20
<br>&gt; more a constructor. I know it is a very elaborate solution to a si=
mple=20
<br>&gt; problem, I was just curious of other peoples' opinions. It seems w=
eird=20
<br>&gt; that making an object const means that it and only it owns that=20
<br>&gt; resource. If that's the way its got to be, so be it. Unfortunately=
,=20
<br>&gt; any innocent const t =3D std::move(getUncopyableType) is a dead en=
d,=20
<br>&gt; even if we intended to move it somewhere else later. (I know stric=
tly=20
<br>&gt; speaking, that's what const should do, but I feel end-of-lifetime =
is a=20
<br>&gt; good chance to avoid it - a non RAII object like const int could b=
e=20
<br>&gt; moved, right?)
<br>&gt;
<br>Well, sorry to say that, but just "don't do it". By marking a variable=
=20
<br>as "const" you make the proimse "I shall not modify this value" and=20
<br>therefore follows "I shall not move from this value". Strictly speaking=
=20
<br>you cannot move from a "const int" either. Technically the compiler=20
<br>calls int's copy constructor (which happens to perform the same=20
<br>operation) as it does for any other type. I can only come up with three=
=20
<br>use cases where marking a value (again, non-reference) as "const" make=
=20
<br>sense:
<br>1. You deliberately want to enforce copy semantics
<br>2. You know the const overload of a method is more efficient
<br>3. You want to get compile errors *if* you modify it by accident
<br>
<br>const is in no way tied to the lifetime of an object or it's associated=
=20
<br>resource. The object itself always owns the resource and some refer to=
=20
<br>this kind of type as a "handle". Making the handle const means "I will=
=20
<br>not change which resource this handle owns". Only one instance of=20
<br>unique_ptr can own an object (unless something went horribly wrong).=20
<br>Whether the unique_ptr itself is const or not has absolutely no impact=
=20
<br>on this guarantee. The const modifier is a promise you make to the=20
<br>compiler (which can be broken with const_cast, but never admit it exist=
s).
<br>
<br>So, basically, don't do
<br>&nbsp; &nbsp; &nbsp;const T t =3D std::move(getUncopyableType)
<br>but instead
<br>&nbsp; &nbsp; &nbsp;auto t =3D std::move(getUncopyableType)
<br>then you can keep on moving from t, and therefore (in your initial=20
<br>example) move the unique_ptr into the new destination unordered_set (an=
d=20
<br>it's less typing, too). Local const values should ring a bell in code=
=20
<br>reviews exactly for the reason that they prohibit move semantics.
<br>
<br>I suggest Scott Meyer's talk from GoingNative 2013 where he elaborates=
=20
<br>this copy/move topic and how const relates to it in more detail:
<br><a href=3D"http://channel9.msdn.com/Events/GoingNative/2013/An-Effectiv=
e-Cpp11-14-Sampler" target=3D"_blank" onmousedown=3D"this.href=3D'http://ww=
w.google.com/url?q\75http%3A%2F%2Fchannel9.msdn.com%2FEvents%2FGoingNative%=
2F2013%2FAn-Effective-Cpp11-14-Sampler\46sa\75D\46sntz\0751\46usg\75AFQjCNH=
HK5Owlr8ZrDU0iRSThK7D_m6x-g';return true;" onclick=3D"this.href=3D'http://w=
ww.google.com/url?q\75http%3A%2F%2Fchannel9.msdn.com%2FEvents%2FGoingNative=
%2F2013%2FAn-Effective-Cpp11-14-Sampler\46sa\75D\46sntz\0751\46usg\75AFQjCN=
HHK5Owlr8ZrDU0iRSThK7D_m6x-g';return true;">http://channel9.msdn.com/<wbr>E=
vents/GoingNative/2013/An-<wbr>Effective-Cpp11-14-Sampler</a>=20
<br>
<br>
<br></blockquote></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/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_57_25221191.1389660790820--

.


Author: David Krauss <potswa@gmail.com>
Date: Tue, 14 Jan 2014 13:29:18 +0800
Raw View
On 1/14/14 8:53 AM, josephlawrie1@gmail.com wrote:
> That kind of behaviour follows from a strict definition of const, and I
> have no problem with it. But I wasn't suggestng that the programmer just
> decides t is const. If t were const (beyond control of the progammer, or
> maybe for a really good reason) than any attempt to copy or move from it
> results in the destructor being called twice. Essentially, c++ struggles to
> deal with the notion of a unique object (no copy constructors) which
> shouldn't me modified. Many people, like yourself, rightly say const
> *should* make this impossible.
>
> Also in the example, there is no interface to move from the container,
> which seems silly to be honest. I'm amazed everyone just says "N3645<http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3645.pdf>/etc will never happen". You can't use c++11's flagship smart pointer in a
> hash table without losing them. I think perl can do that...

I think "it will never happen" is too strong, but you have to look at
how container internals work. In the case of a map, the value_type is
defined to be a std::pair with a const "first" member. So the key object
itself is const, and removing the const by const_cast is illegal. But in
the case of a set, the specification of const value_type does not
require the key object itself to be const; it only requires that
references returned to the user be const.

It's easy for set provide extract semantics by preserving write access
internally. The solution for map would be to do the same. The problem is
the lack of a suitable cast from pair< T, U > & to pair< T const, U > &
at the observer interfaces. It's not an issue for a special destructor
at all, it's about aliasing between different class types.

Being able to change the "write permission" on subcomponents of a
structure at interface boundaries without copying is a fundamental issue
which even affects the C language as well. In olden days many
programmers just violated aliasing rules, if they existed in the first
place, but in the current era the difference between class types with
similar definitions is taken seriously. Perhaps this is an area to
revisit aliasing and class layout rules. There are several others.

To be sure, standard library implementations only need to work per the
as-if rule; they do not need to follow the C++ object model behind the
scenes or even to be written in C++. This case of aliasing is not
actually a practical problem, since by the time of lvalue-to-rvalue
conversion the type being accessed is always correct. The only hitch
with storing internally a std::pair< T, U > is that the user may have
specialized std::pair< T const, U > and they could then observe the
difference.

Therefore, the only normative change required to allow an implementation
to support extract() is to disallow user specializations of std::pair
from coinciding with map container value_types. Then the implementation
is free to define another class type with de-facto layout compatibility
to the primary specialization of std::pair< T const, U >, and
reinterpret_cast between the two (or whatever).

--

---
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/.

.


Author: David Krauss <potswa@gmail.com>
Date: Tue, 14 Jan 2014 14:11:33 +0800
Raw View
On 1/14/14 1:29 PM, David Krauss wrote:
> Therefore, the only normative change required to allow an
> implementation to support extract() is to disallow user
> specializations of std::pair from coinciding with map container
> value_types. Then the implementation is free to define another class
> type with de-facto layout compatibility to the primary specialization
> of std::pair< T const, U >, and reinterpret_cast between the two (or
> whatever).

Of course, an implementation could also just perform the illegal
const_cast whilst moving the key and mapped value separately within
extract(), and implement correct semantics under the umbrella of UB.

What's possible for the standard library and what's possible for a user
are different things.

Whether it's better to deny standard library capabilities to users until
they can be matched by third-party libraries is another question.

--

---
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/.

.