Topic: Adding 'extract' method to containers


Author: Xavi Gratal <gratal@gmail.com>
Date: Sat, 16 Nov 2013 19:02:02 -0800 (PST)
Raw View
------=_Part_1355_20233865.1384657322746
Content-Type: text/plain; charset=ISO-8859-1

Since the introduction of move semantics, I find myself often using
containers to temporarily hold movable objects, such as unique_ptr. The
syntax for adding a pointer to, for example, a map is rather intuitive:

std::map<int,std::unique_ptr<A>> my_map;

my_map.emplace(1, get_new_unique_ptr());


However, when I need to extract one of these pointers from the map, I have
to do all of the following:

auto i=my_map.find(1);
if(i==my_map.end()) throw ...; //just in case
auto ptr=std::move(i->second);
my_map.erase(i);

I propose adding an 'extract' method to associative containers, so that I
can just use:

auto ptr=my_map.extract(1);

This method should, just like 'at', throw out_of_range if it is not found,
and otherwise move the value out of the container. Of course overloads
taking iterators could also be possible, as exist for 'erase', and it could
also be added to non-associative containers, which could even have
extract_front and extract_back methods, but I find this case particularly
useful.

Has anything similar been proposed before? A quick search yielded nothing.
Would anyone be interested?

--

---
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_1355_20233865.1384657322746
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">Since the introduction of move semantics, I find myself of=
ten using containers to temporarily hold movable objects, such as unique_pt=
r. The syntax for adding a pointer to, for example, a map is rather intuiti=
ve:<div><br></div><div class=3D"prettyprint" style=3D"background-color: rgb=
(250, 250, 250); border: 1px solid rgb(187, 187, 187); word-wrap: break-wor=
d;"><code class=3D"prettyprint"><div class=3D"subprettyprint"><span style=
=3D"color: #000;" class=3D"styled-by-prettify">std</span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">::</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify">map</span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">&lt;</span><span style=3D"color: #008;" class=3D"s=
tyled-by-prettify">int</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">,</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y">std</span><span style=3D"color: #660;" class=3D"styled-by-prettify">::</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify">unique_ptr</=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">&lt;</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify">A</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">&gt;&gt;</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> my_map</span><span style=3D=
"color: #660;" class=3D"styled-by-prettify">;</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"><br><br>my_map</span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">.</span><span style=3D"color: #000;"=
 class=3D"styled-by-prettify">emplace</span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">(</span><span style=3D"color: #066;" class=3D"st=
yled-by-prettify">1</span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">,</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
 get_new_unique_ptr</span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">());</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"><br></span></div></code></div><div><br><br></div><div>However, when I ne=
ed to extract one of these pointers from the map, I have to do all of the f=
ollowing:</div><div><br></div><div class=3D"prettyprint" style=3D"backgroun=
d-color: rgb(250, 250, 250); border: 1px solid rgb(187, 187, 187); word-wra=
p: break-word;"><code class=3D"prettyprint"><div class=3D"subprettyprint"><=
span style=3D"color: #008;" class=3D"styled-by-prettify">auto</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"> i</span><span style=3D"=
color: #660;" class=3D"styled-by-prettify">=3D</span><span style=3D"color: =
#000;" class=3D"styled-by-prettify">my_map</span><span style=3D"color: #660=
;" class=3D"styled-by-prettify">.</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify">find</span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">(</span><span style=3D"color: #066;" class=3D"styled-by-p=
rettify">1</span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
);</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></sp=
an><span style=3D"color: #008;" class=3D"styled-by-prettify">if</span><span=
 style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify">i</span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">=3D=3D</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify">my_map</span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">.</span><span style=3D"color: #008;" class=3D"st=
yled-by-prettify">end</span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">())</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">throw=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">...;</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"co=
lor: #800;" class=3D"styled-by-prettify">//just in case</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span style=3D"co=
lor: #008;" class=3D"styled-by-prettify">auto</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"> ptr</span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">=3D</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify">std</span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">::</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify">move</span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">(</span><span style=3D"color: #000;" class=3D"styled-by-prettify">i</spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">-&gt;</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify">second</span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">);</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"><br>my_map</span><span style=3D"=
color: #660;" class=3D"styled-by-prettify">.</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify">erase</span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">(</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify">i</span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">);</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"><br></span></div></code></div><div><br><span style=3D"font-size: 13px;">=
I propose adding an 'extract' method to associative containers, so that I c=
an just use:</span><br></div><div><span style=3D"font-size: 13px;"><br></sp=
an></div><div><span style=3D"font-size: 13px;"><div class=3D"prettyprint" s=
tyle=3D"background-color: rgb(250, 250, 250); border: 1px solid rgb(187, 18=
7, 187); word-wrap: break-word;"><code class=3D"prettyprint"><div class=3D"=
subprettyprint"><span style=3D"color: #008;" class=3D"styled-by-prettify">a=
uto</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> ptr</s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify">my_map</span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">.</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify">extract</span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #066;"=
 class=3D"styled-by-prettify">1</span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">);</span></div></code></div><br></span></div><div><spa=
n style=3D"font-size: 13px;">This method should, just like 'at', throw out_=
of_range if it is not found, and otherwise move the value out of the contai=
ner. Of course overloads taking iterators could also be possible, as exist =
for 'erase', and it could also be added to non-associative containers, whic=
h could even have extract_front and extract_back methods, but I find this c=
ase particularly useful.</span></div><div><span style=3D"font-size: 13px;">=
<br></span></div><div>Has anything similar been proposed before? A quick se=
arch yielded nothing. Would anyone be interested?</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_1355_20233865.1384657322746--

.


Author: David Krauss <potswa@gmail.com>
Date: Sun, 17 Nov 2013 12:59:28 +0800
Raw View
On 11/17/13 11:02 AM, Xavi Gratal wrote:
> However, when I need to extract one of these pointers from the map, I have
> to do all of the following:
>
> auto i=my_map.find(1);
> if(i==my_map.end()) throw ...; //just in case
> auto ptr=std::move(i->second);
> my_map.erase(i);
>
> I propose adding an 'extract' method to associative containers, so that I
> can just use:
>
> auto ptr=my_map.extract(1);
>
> This method should, just like 'at', throw out_of_range if it is not found,
> and otherwise move the value out of the container.

Doesn't this mean your boilerplate is excessive, and you could just do

auto ptr = std::move( my_map.at( 1 ) );

The only difference I see is control over what exception gets thrown.
Perhaps it would be nice to be able to specify that as an optional
template argument to at(). Before C++11 we didn't have function template
default arguments.

I think perhaps what you really want is the ability to extract the key,
which can never be modified or moved-from:

std::pair< big_int, std::unique_ptr< foo > > kv_pair = my_map.extract( 1 );

>   Of course overloads
> taking iterators could also be possible, as exist for 'erase', and it could
> also be added to non-associative containers, which could even have
> extract_front and extract_back methods, but I find this case particularly
> useful.

There would only be new capability when the value_type is const. I favor
support for const value_types in general so the ability to extract
values would be great.

> Has anything similar been proposed before? A quick search yielded nothing.
> Would anyone be interested?

Not sure it's related, but this reminds me of another case, where you
want to add an object into a map but only if it's not already there.

auto i = m.find( key );
if ( i == m.end() ) throw exc( "Duplicate key", std::move( key ) );
m.insert( std::make_pair( std::move( key ), std::move( value ) ) );

This should be replaced with

if ( ! m.insert( std::make_pair( std::move( key ), std::move( value ) )
).first ) {
     throw exc( "Duplicate key", std::move( key ) );
}

The problem is that the rvalue overload of insert moves from its
argument even if it's unused. It seems simple to specify that arguments
shouldn't be moved from and subsequently discarded. There would be a
problem if there were a single overload with pass by value rather than
two overloads, but there is not. Instead there is a perfect forward
overload specifying an unnecessary rvalue reference to prvalue conversion.

--

---
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: xavi <gratal@gmail.com>
Date: Sun, 17 Nov 2013 07:06:09 +0100
Raw View
--047d7bd75c9453403204eb593a18
Content-Type: text/plain; charset=ISO-8859-1

2013/11/17 David Krauss <potswa@gmail.com>

> On 11/17/13 11:02 AM, Xavi Gratal wrote:
>
>> However, when I need to extract one of these pointers from the map, I have
>> to do all of the following:
>>
>> auto i=my_map.find(1);
>> if(i==my_map.end()) throw ...; //just in case
>> auto ptr=std::move(i->second);
>> my_map.erase(i);
>>
>> I propose adding an 'extract' method to associative containers, so that I
>> can just use:
>>
>> auto ptr=my_map.extract(1);
>>
>> This method should, just like 'at', throw out_of_range if it is not found,
>> and otherwise move the value out of the container.
>>
>
> Doesn't this mean your boilerplate is excessive, and you could just do
>
> auto ptr = std::move( my_map.at( 1 ) );
>
> the difference is that the extract method would also erase it from the
container, so all the lines above are really necessary to replace it.


> The only difference I see is control over what exception gets thrown.
> Perhaps it would be nice to be able to specify that as an optional template
> argument to at(). Before C++11 we didn't have function template default
> arguments.
>
> I think perhaps what you really want is the ability to extract the key,
> which can never be modified or moved-from:
>
> std::pair< big_int, std::unique_ptr< foo > > kv_pair = my_map.extract( 1 );
>
> I can't come up with any interesting case where keys don't have value
semantics. If people are using such keys, then this could be useful too.

>
>    Of course overloads
>> taking iterators could also be possible, as exist for 'erase', and it
>> could
>> also be added to non-associative containers, which could even have
>> extract_front and extract_back methods, but I find this case particularly
>> useful.
>>
>
> There would only be new capability when the value_type is const. I favor
> support for const value_types in general so the ability to extract values
> would be great.
>
> I think that being able to obtain and erase in a single operation is nice.
I've always been surprised (though I understand the reasons) that pop_front
and pop_back don't return the value.

>
>  Has anything similar been proposed before? A quick search yielded nothing.
>> Would anyone be interested?
>>
>
> Not sure it's related, but this reminds me of another case, where you want
> to add an object into a map but only if it's not already there.
>
> auto i = m.find( key );
> if ( i == m.end() ) throw exc( "Duplicate key", std::move( key ) );
> m.insert( std::make_pair( std::move( key ), std::move( value ) ) );
>
> This should be replaced with
>
> if ( ! m.insert( std::make_pair( std::move( key ), std::move( value ) )
> ).first ) {
>     throw exc( "Duplicate key", std::move( key ) );
> }
>
> The problem is that the rvalue overload of insert moves from its argument
> even if it's unused. It seems simple to specify that arguments shouldn't be
> moved from and subsequently discarded. There would be a problem if there
> were a single overload with pass by value rather than two overloads, but
> there is not. Instead there is a perfect forward overload specifying an
> unnecessary rvalue reference to prvalue conversion.
>
>
> The problem there is that make_pair moves from its argument, not insert.
At least in gcc 4.8.2, the following code:

    std::map<int,std::unique_ptr<int>> my_map;
    std::unique_ptr<int> a(new int);
    std::unique_ptr<int> b(new int);
    my_map.insert(std::pair<int,std::unique_ptr<int>&&>(1,std::move(a)));
    my_map.insert(std::pair<int,std::unique_ptr<int>&&>(1,std::move(b)));
    std::cout << (bool)a << (bool)b << "\n";

prints 01, which means that b was never moved from. If we had something
like forward_as_pair, analogous for pairs of forward_as_tuple, that should
work too.

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

--

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

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

<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><br><div class=3D"gmail=
_quote">2013/11/17 David Krauss <span dir=3D"ltr">&lt;<a href=3D"mailto:pot=
swa@gmail.com" target=3D"_blank">potswa@gmail.com</a>&gt;</span><br><blockq=
uote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-wi=
dth:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-=
left:1ex">
<div class=3D"im">On 11/17/13 11:02 AM, Xavi Gratal wrote:<br>
<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">
However, when I need to extract one of these pointers from the map, I have<=
br>
to do all of the following:<br>
<br>
auto i=3Dmy_map.find(1);<br>
if(i=3D=3Dmy_map.end()) throw ...; //just in case<br>
auto ptr=3Dstd::move(i-&gt;second);<br>
my_map.erase(i);<br>
<br>
I propose adding an &#39;extract&#39; method to associative containers, so =
that I<br>
can just use:<br>
<br>
auto ptr=3Dmy_map.extract(1);<br>
<br>
This method should, just like &#39;at&#39;, throw out_of_range if it is not=
 found,<br>
and otherwise move the value out of the container.<br>
</blockquote>
<br></div>
Doesn&#39;t this mean your boilerplate is excessive, and you could just do<=
br>
<br>
auto ptr =3D std::move( <a href=3D"http://my_map.at" target=3D"_blank">my_m=
ap.at</a>( 1 ) );<br>
<br></blockquote><div>the difference is that the extract method would also =
erase it from the container, so all the lines above are really necessary to=
 replace it.</div><div>=A0</div><blockquote class=3D"gmail_quote" style=3D"=
margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,20=
4,204);border-left-style:solid;padding-left:1ex">

The only difference I see is control over what exception gets thrown. Perha=
ps it would be nice to be able to specify that as an optional template argu=
ment to at(). Before C++11 we didn&#39;t have function template default arg=
uments.<br>

<br>
I think perhaps what you really want is the ability to extract the key, whi=
ch can never be modified or moved-from:<br>
<br>
std::pair&lt; big_int, std::unique_ptr&lt; foo &gt; &gt; kv_pair =3D my_map=
..extract( 1 );<div class=3D"im"><br></div></blockquote><div>I can&#39;t com=
e up with any interesting case where keys don&#39;t have value semantics. I=
f people are using such keys, then this could be useful too.=A0</div>
<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"><div class=3D"im">
<br>
<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">
=A0 Of course overloads<br>
taking iterators could also be possible, as exist for &#39;erase&#39;, and =
it could<br>
also be added to non-associative containers, which could even have<br>
extract_front and extract_back methods, but I find this case particularly<b=
r>
useful.<br>
</blockquote>
<br></div>
There would only be new capability when the value_type is const. I favor su=
pport for const value_types in general so the ability to extract values wou=
ld be great.<div class=3D"im"><br></div></blockquote><div>I think that bein=
g able to obtain and erase in a single operation is nice. I&#39;ve always b=
een surprised (though I understand the reasons) that pop_front and pop_back=
 don&#39;t return the value.=A0</div>
<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"><div class=3D"im">
<br>
<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">
Has anything similar been proposed before? A quick search yielded nothing.<=
br>
Would anyone be interested?<br>
</blockquote>
<br></div>
Not sure it&#39;s related, but this reminds me of another case, where you w=
ant to add an object into a map but only if it&#39;s not already there.<br>
<br>
auto i =3D m.find( key );<br>
if ( i =3D=3D m.end() ) throw exc( &quot;Duplicate key&quot;, std::move( ke=
y ) );<br>
m.insert( std::make_pair( std::move( key ), std::move( value ) ) );<br>
<br>
This should be replaced with<br>
<br>
if ( ! m.insert( std::make_pair( std::move( key ), std::move( value ) ) ).f=
irst ) {<br>
=A0 =A0 throw exc( &quot;Duplicate key&quot;, std::move( key ) );<br>
}<br>
<br>
The problem is that the rvalue overload of insert moves from its argument e=
ven if it&#39;s unused. It seems simple to specify that arguments shouldn&#=
39;t be moved from and subsequently discarded. There would be a problem if =
there were a single overload with pass by value rather than two overloads, =
but there is not. Instead there is a perfect forward overload specifying an=
 unnecessary rvalue reference to prvalue conversion.<div class=3D"">
<div class=3D"h5"><br>
<br></div></div></blockquote><div>The problem there is that make_pair moves=
 from its argument, not insert. At least in gcc 4.8.2, the following code:<=
/div><div><br></div>







=A0 =A0 std::map&lt;int,std::unique_ptr&lt;int&gt;&gt; my_map;<br>=A0 =A0 s=
td::unique_ptr&lt;int&gt; a(new int);<br>=A0 =A0 std::unique_ptr&lt;int&gt;=
 b(new int);<br>=A0 =A0 my_map.insert(std::pair&lt;int,std::unique_ptr&lt;i=
nt&gt;&amp;&amp;&gt;(1,std::move(a)));<br>
=A0 =A0 my_map.insert(std::pair&lt;int,std::unique_ptr&lt;int&gt;&amp;&amp;=
&gt;(1,std::move(b)));<br><div>=A0 =A0=A0std::cout &lt;&lt; (<span class=3D=
"">bool</span>)a &lt;&lt; (<span class=3D"">bool</span>)b &lt;&lt; <span cl=
ass=3D"">&quot;</span><span class=3D"">\n</span><span class=3D"">&quot;</sp=
an>;=A0</div>
<div><br></div><div>prints 01, which means that b was never moved from. If =
we had something like forward_as_pair, analogous for pairs of forward_as_tu=
ple, that should work too.</div><div><br></div><blockquote class=3D"gmail_q=
uote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-c=
olor:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<div class=3D""><div class=3D"h5">
-- <br>
<br>
--- You received this message because you are subscribed to the Google Grou=
ps &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 <a href=3D"mailto:std-proposals%2Bunsubscribe@isocpp.org" target=3D=
"_blank">std-proposals+unsubscribe@<u></u>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/" target=3D"_blank">http://groups.google.com/a/<u></u>isocpp.=
org/group/std-<u></u>proposals/</a>.<br>
</div></div></blockquote></div><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 />

--047d7bd75c9453403204eb593a18--

.


Author: David Krauss <potswa@gmail.com>
Date: Sun, 17 Nov 2013 14:37:03 +0800
Raw View
On 11/17/13 2:06 PM, xavi wrote:

> the difference is that the extract method would also erase it from the
> container, so all the lines above are really necessary to replace it.

Oh, right.

By the way, I wonder if non-primitive, optional container operations=20
should be supplied as free functions as well as members of standard=20
containers. Then user-defined containers could benefit as well. Class=20
interface bloat is a red flag and the standard containers are getting=20
huge, and repetitious.

>> I can't come up with any interesting case where keys don't have value
> semantics. If people are using such keys, then this could be useful too.

It comes up more often with std::set.

> The problem there is that make_pair moves from its argument, not insert.

You're right, but actually both move from their respective arguments. A=20
better example would use std::set.

> If we had something like forward_as_pair, analogous for pairs of=20
> forward_as_tuple, that should work too.=20

That reveals another problem, that insert needs to use the key subobject=20
to perform a lookup without copying it.

I think a proper rvalue value_type && overload is needed in addition to=20
the perfect forwarding overload. I was surprised to see perfect=20
forwarding there just now; it's very non-canonical. Maybe the perfect=20
forwarding and conversion within the insert() bit should go away =97 just=
=20
remove that overload entirely.

I haven't done the background research or checked for existing DRs in=20
this area, just wanted to mention that it's a peeve of mine. Sorry to=20
hijack your thread.

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

.


Author: Jared Grubb <jared.grubb@gmail.com>
Date: Sat, 16 Nov 2013 22:39:29 -0800 (PST)
Raw View
------=_Part_5_31624167.1384670369559
Content-Type: text/plain; charset=ISO-8859-1

Trick Question: How do you get a unique_ptr out of a set?
Answer: You cant!

I think having such "get+erase" operations would be very useful.

Jared

On Saturday, November 16, 2013 7:02:02 PM UTC-8, Xavi Gratal wrote:
>
> Since the introduction of move semantics, I find myself often using
> containers to temporarily hold movable objects, such as unique_ptr. The
> syntax for adding a pointer to, for example, a map is rather intuitive:
>
> std::map<int,std::unique_ptr<A>> my_map;
>
> my_map.emplace(1, get_new_unique_ptr());
>
>
> However, when I need to extract one of these pointers from the map, I have
> to do all of the following:
>
> auto i=my_map.find(1);
> if(i==my_map.end()) throw ...; //just in case
> auto ptr=std::move(i->second);
> my_map.erase(i);
>
> I propose adding an 'extract' method to associative containers, so that I
> can just use:
>
> auto ptr=my_map.extract(1);
>
> This method should, just like 'at', throw out_of_range if it is not found,
> and otherwise move the value out of the container. Of course overloads
> taking iterators could also be possible, as exist for 'erase', and it could
> also be added to non-associative containers, which could even have
> extract_front and extract_back methods, but I find this case particularly
> useful.
>
> Has anything similar been proposed before? A quick search yielded nothing.
> Would anyone be interested?
>

--

---
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_5_31624167.1384670369559
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><div><span style=3D"font-size: 13px;">Trick Question: How =
do you get a unique_ptr out of a set?&nbsp;</span><br></div><div><span styl=
e=3D"font-size: 13px;">Answer: You cant!</span></div><div><br></div><div><d=
iv>I think having such "get+erase" operations would be very useful.&nbsp;</=
div><div><span style=3D"font-size: 13px;"><br></span></div></div><div><span=
 style=3D"font-size: 13px;">Jared</span><br></div><div><br>On Saturday, Nov=
ember 16, 2013 7:02:02 PM UTC-8, Xavi Gratal wrote:<blockquote class=3D"gma=
il_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid=
;padding-left: 1ex;"><div dir=3D"ltr">Since the introduction of move semant=
ics, I find myself often using containers to temporarily hold movable objec=
ts, such as unique_ptr. The syntax for adding a pointer to, for example, a =
map is rather intuitive:<div><br></div><div style=3D"background-color:rgb(2=
50,250,250);border:1px solid rgb(187,187,187);word-wrap:break-word"><code><=
div><span style=3D"color:#000">std</span><span style=3D"color:#660">::</spa=
n><span style=3D"color:#000">map</span><span style=3D"color:#660">&lt;</spa=
n><span style=3D"color:#008">int</span><span style=3D"color:#660">,</span><=
span style=3D"color:#000">std</span><span style=3D"color:#660">::</span><sp=
an style=3D"color:#000">unique_ptr</span><span style=3D"color:#660">&lt;</s=
pan><span style=3D"color:#000">A</span><span style=3D"color:#660"><wbr>&gt;=
&gt;</span><span style=3D"color:#000"> my_map</span><span style=3D"color:#6=
60">;</span><span style=3D"color:#000"><br><br>my_map</span><span style=3D"=
color:#660">.</span><span style=3D"color:#000">emplace</span><span style=3D=
"color:#660">(</span><span style=3D"color:#066">1</span><span style=3D"colo=
r:#660">,</span><span style=3D"color:#000"> get_new_unique_ptr</span><span =
style=3D"color:#660">());</span><span style=3D"color:#000"><br></span></div=
></code></div><div><br><br></div><div>However, when I need to extract one o=
f these pointers from the map, I have to do all of the following:</div><div=
><br></div><div style=3D"background-color:rgb(250,250,250);border:1px solid=
 rgb(187,187,187);word-wrap:break-word"><code><div><span style=3D"color:#00=
8">auto</span><span style=3D"color:#000"> i</span><span style=3D"color:#660=
">=3D</span><span style=3D"color:#000">my_map</span><span style=3D"color:#6=
60">.</span><span style=3D"color:#000">find</span><span style=3D"color:#660=
">(</span><span style=3D"color:#066">1</span><span style=3D"color:#660">);<=
/span><span style=3D"color:#000"><br></span><span style=3D"color:#008">if</=
span><span style=3D"color:#660">(</span><span style=3D"color:#000">i</span>=
<span style=3D"color:#660">=3D=3D</span><span style=3D"color:#000">my_map</=
span><span style=3D"color:#660">.</span><span style=3D"color:#008">end</spa=
n><span style=3D"color:#660">())</span><span style=3D"color:#000"> </span><=
span style=3D"color:#008">throw</span><span style=3D"color:#000"> </span><s=
pan style=3D"color:#660">...;</span><span style=3D"color:#000"> </span><spa=
n style=3D"color:#800">//just in case</span><span style=3D"color:#000"><br>=
</span><span style=3D"color:#008">auto</span><span style=3D"color:#000"> pt=
r</span><span style=3D"color:#660">=3D</span><span style=3D"color:#000">std=
</span><span style=3D"color:#660">::</span><span style=3D"color:#000">move<=
/span><span style=3D"color:#660">(</span><span style=3D"color:#000">i</span=
><span style=3D"color:#660">-&gt;</span><span style=3D"color:#000">second</=
span><span style=3D"color:#660">);</span><span style=3D"color:#000"><br>my_=
map</span><span style=3D"color:#660">.</span><span style=3D"color:#000">era=
se</span><span style=3D"color:#660">(</span><span style=3D"color:#000">i</s=
pan><span style=3D"color:#660">);</span><span style=3D"color:#000"><br></sp=
an></div></code></div><div><br><span style=3D"font-size:13px">I propose add=
ing an 'extract' method to associative containers, so that I can just use:<=
/span><br></div><div><span style=3D"font-size:13px"><br></span></div><div><=
span style=3D"font-size:13px"><div style=3D"background-color:rgb(250,250,25=
0);border:1px solid rgb(187,187,187);word-wrap:break-word"><code><div><span=
 style=3D"color:#008">auto</span><span style=3D"color:#000"> ptr</span><spa=
n style=3D"color:#660">=3D</span><span style=3D"color:#000">my_map</span><s=
pan style=3D"color:#660">.</span><span style=3D"color:#000">extract</span><=
span style=3D"color:#660">(</span><span style=3D"color:#066">1</span><span =
style=3D"color:#660">);</span></div></code></div><br></span></div><div><spa=
n style=3D"font-size:13px">This method should, just like 'at', throw out_of=
_range if it is not found, and otherwise move the value out of the containe=
r. Of course overloads taking iterators could also be possible, as exist fo=
r 'erase', and it could also be added to non-associative containers, which =
could even have extract_front and extract_back methods, but I find this cas=
e particularly useful.</span></div><div><span style=3D"font-size:13px"><br>=
</span></div><div>Has anything similar been proposed before? A quick search=
 yielded nothing. Would anyone be interested?</div></div></blockquote></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_5_31624167.1384670369559--

.


Author: xavi <gratal@gmail.com>
Date: Sun, 17 Nov 2013 08:29:48 +0100
Raw View
--047d7b5dbf62791e4004eb5a65f3
Content-Type: text/plain; charset=windows-1252
Content-Transfer-Encoding: quoted-printable

2013/11/17 David Krauss <potswa@gmail.com>

> On 11/17/13 2:06 PM, xavi wrote:
>
>  the difference is that the extract method would also erase it from the
>> container, so all the lines above are really necessary to replace it.
>>
>
> Oh, right.
>
> By the way, I wonder if non-primitive, optional container operations
> should be supplied as free functions as well as members of standard
> containers. Then user-defined containers could benefit as well. Class
> interface bloat is a red flag and the standard containers are getting hug=
e,
> and repetitious.
>
> In some cases that's possible, but as Jared pointed out, for getting a
pointer out of std::set it must be a member function, because it's not
possible to do it with the current interface.

>
>  I can't come up with any interesting case where keys don't have value
>>>
>> semantics. If people are using such keys, then this could be useful too.
>>
>
> It comes up more often with std::set.
>
>
>  The problem there is that make_pair moves from its argument, not insert.
>>
>
> You're right, but actually both move from their respective arguments. A
> better example would use std::set.
>
> No they don't. map::insert doesn't move from its argument unless it is
actually inserted. And neither does set::insert. The following code

    std::set<std::unique_ptr<int>> my_set;
    int *p=3Dnew int;
    std::unique_ptr<int> a(p);
    std::unique_ptr<int> b(p);
    my_set.insert(std::move(a));
    my_set.insert(std::move(b));
    std::cout << (bool)a << (bool)b << "\n";

prints again 01, which means that the second insertion doesn't move from
the object, since it's already there.

And of course it also segfaults because it deletes the integer twice, but
it's hard to come up with cases where the key to an associative container
is not copiable but having two objects that compare equal makes sense.

>
>  If we had something like forward_as_pair, analogous for pairs of
>> forward_as_tuple, that should work too.
>>
>
> That reveals another problem, that insert needs to use the key subobject
> to perform a lookup without copying it.
>
> I think a proper rvalue value_type && overload is needed in addition to
> the perfect forwarding overload. I was surprised to see perfect forwardin=
g
> there just now; it's very non-canonical. Maybe the perfect forwarding and
> conversion within the insert() bit should go away =97 just remove that
> overload entirely.
>
> And with perfect forwarding it can perform the lookup without copying it.
I think insert works perfectly well as is now.

> I haven't done the background research or checked for existing DRs in thi=
s
> area, just wanted to mention that it's a peeve of mine. Sorry to hijack
> your thread.
>
>
> --
>
> --- 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/.
>

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

--047d7b5dbf62791e4004eb5a65f3
Content-Type: text/html; charset=windows-1252
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><br><div class=3D"gmail=
_quote">2013/11/17 David Krauss <span dir=3D"ltr">&lt;<a href=3D"mailto:pot=
swa@gmail.com" target=3D"_blank">potswa@gmail.com</a>&gt;</span><br><blockq=
uote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-wi=
dth:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-=
left:1ex">
<div class=3D"im">On 11/17/13 2:06 PM, xavi wrote:<br>
<br>
<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">
the difference is that the extract method would also erase it from the<br>
container, so all the lines above are really necessary to replace it.<br>
</blockquote>
<br></div>
Oh, right.<br>
<br>
By the way, I wonder if non-primitive, optional container operations should=
 be supplied as free functions as well as members of standard containers. T=
hen user-defined containers could benefit as well. Class interface bloat is=
 a red flag and the standard containers are getting huge, and repetitious.<=
div class=3D"im">
<br></div></blockquote><div>In some cases that&#39;s possible, but as Jared=
 pointed out, for getting a pointer out of std::set it must be a member fun=
ction, because it&#39;s not possible to do it with the current interface.=
=A0</div>
<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"><div class=3D"im">
<br>
<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"><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-l=
eft-style:solid;padding-left:1ex">

I can&#39;t come up with any interesting case where keys don&#39;t have val=
ue<br>
</blockquote>
semantics. If people are using such keys, then this could be useful too.<br=
>
</blockquote>
<br></div>
It comes up more often with std::set.<div class=3D"im"><br>
<br>
<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">
The problem there is that make_pair moves from its argument, not insert.<br=
>
</blockquote>
<br></div>
You&#39;re right, but actually both move from their respective arguments. A=
 better example would use std::set.<div class=3D"im"><br></div></blockquote=
><div>No they don&#39;t. map::insert doesn&#39;t move from its argument unl=
ess it is actually inserted. And neither does set::insert. The following co=
de</div>
<div><br></div><div>=A0 =A0 std::set&lt;std::unique_ptr&lt;int&gt;&gt; my_s=
et;</div><div>=A0=A0 =A0int *p=3Dnew int;</div><div>=A0 =A0 std::unique_ptr=
&lt;int&gt; a(p); =A0 =A0 =A0=A0</div><div>=A0 =A0 std::unique_ptr&lt;int&g=
t; b(p); =A0 =A0 =A0=A0</div><div>
=A0 =A0 my_set.insert(std::move(a));</div><div>=A0=A0 =A0my_set.insert(std:=
:move(b));</div><div>=A0=A0 =A0std::cout &lt;&lt; (bool)a &lt;&lt; (bool)b =
&lt;&lt; &quot;\n&quot;;=A0</div><div><br></div><div>prints again 01, which=
 means that the second insertion doesn&#39;t move from the object, since it=
&#39;s already there.</div>
<div><br></div><div>And of course it also segfaults because it deletes the =
integer twice, but it&#39;s hard to come up with cases where the key to an =
associative container is not copiable but having two objects that compare e=
qual makes sense.</div>
<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"><div class=3D"im">
<br>
<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 we had something like forward_as_pair, analogous for pairs of forward_as=
_tuple, that should work too. <br>
</blockquote>
<br></div>
That reveals another problem, that insert needs to use the key subobject to=
 perform a lookup without copying it.<br>
<br>
I think a proper rvalue value_type &amp;&amp; overload is needed in additio=
n to the perfect forwarding overload. I was surprised to see perfect forwar=
ding there just now; it&#39;s very non-canonical. Maybe the perfect forward=
ing and conversion within the insert() bit should go away =97 just remove t=
hat overload entirely.<br>

<br></blockquote><div>And with perfect forwarding it can perform the lookup=
 without copying it. I think insert works perfectly well as is now.=A0</div=
><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;=
padding-left:1ex">

I haven&#39;t done the background research or checked for existing DRs in t=
his area, just wanted to mention that it&#39;s a peeve of mine. Sorry to hi=
jack your thread.<div class=3D""><div class=3D"h5"><br>
<br>
-- <br>
<br>
--- You received this message because you are subscribed to the Google Grou=
ps &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 <a href=3D"mailto:std-proposals%2Bunsubscribe@isocpp.org" target=3D=
"_blank">std-proposals+unsubscribe@<u></u>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/" target=3D"_blank">http://groups.google.com/a/<u></u>isocpp.=
org/group/std-<u></u>proposals/</a>.<br>
</div></div></blockquote></div><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 />

--047d7b5dbf62791e4004eb5a65f3--

.