Topic: Allowing uncopyable allocators


Author: quicknir@gmail.com
Date: Sat, 16 Jan 2016 15:38:45 -0800 (PST)
Raw View
------=_Part_176_1034829407.1452987525462
Content-Type: multipart/alternative;
 boundary="----=_Part_177_425754619.1452987525462"

------=_Part_177_425754619.1452987525462
Content-Type: text/plain; charset=UTF-8

Currently, allocators seem to be absolutely required to be copy
constructable. This is actually a very stringent requirement; the copy
constructed allocator must compare equal to the original allocator, which
for allocators implies that they can allocate and deallocate each other's
pointers. This is fine if your allocators simply hold pointers back to a
memory pool. But what if your allocators want to own their own resources?
Such allocators can never really allocate or deallocate each other's
pointers, so they can never compare equal. This sounds like a big deal, but
if your allocator is uncopyable, then it's not an issue; there's no real
situation where you would ever necessarily expect them to compare equal.
The current requirement of copyability is artificial though, all of the
tools are already in place to avoid it. An allocator that sets
propagate_on_container_copy_assignment to false  already doesn't need to be
copy assignable. And if an allocator defines
select_on_container_copy_construction it is never "conceptually" copied.
Consider the following example:

#include <vector>
#include <iostream>

template <class T>
struct SimpleAllocator {
  typedef T value_type;
  SimpleAllocator() = default;
  template <class U> SimpleAllocator(const SimpleAllocator<U>& other) {};
  T* allocate(std::size_t n) { return new T[n]; };
  void deallocate(T* p, std::size_t n) { delete [] p; };

  SimpleAllocator(const SimpleAllocator&) { std::cerr << "copy\n"; };
  SimpleAllocator(SimpleAllocator&&) = default;
  SimpleAllocator& operator=(const SimpleAllocator&) = delete;
  SimpleAllocator& operator=(SimpleAllocator&&) = default;

  SimpleAllocator select_on_container_copy_construction() const {
    std::cerr << "blah\n";
    return SimpleAllocator{};
  }
};

template <class T, class U>
bool operator==(const SimpleAllocator<T>&, const SimpleAllocator<U>&) {
return true; }
template <class T, class U>
bool operator!=(const SimpleAllocator<T>&, const SimpleAllocator<U>&) {
return false; }

int main(int argc, char **argv) {
  std::vector<double, SimpleAllocator<double>> x{1.0};
  std::cerr << x[0] << "\n";
  auto y = x;
}

This example runs and prints:

copy
1
blah
copy

So constructing our container, which should simply default construct an
allocator, also makes a copy, despite there being no "conceptual" copy.
When we copy construct, we create a new allocator using
select_on_container_copy_construction, and copy that new allocator, which
is also unnecessary.

If these unnecessary copies were eliminated, then it would actually be
quite simple  to write allocators that owned their own resources. Such an
allocator just needs a default constructor and move/swap, which is
typically  These have multiple applications:

   - For data structures that perform many small allocations (like map and
   set), such an allocator would allow making some speed vs space trade-offs
   by chunking up allocations. This can be done in the current framework, but
   requires introducing a memory pool, which often has separate lifetime, or
   perhaps is co-owned by its allocators via shared_ptr. Using an owning
   allocator is much simpler and hassle free; it is a drop in replacement with
   a typedef.
   - It allows one to force the small X optimization on any data structure
   (less efficiently, of course). For instance, one could create an allocator
   that deliberately contains 64 bytes of empty storage. Allocation requests
   for 64 bytes or less are served from this buffer, anything larger is sent
   to the heap. Convenient e.g. for std::function, or std::vector, and easy to
   customize.
   - It has interesting possibilities combined with scoped_allocators. I
   admit I haven't investigated these in depth, but it seems like it would
   allow scenarios similar to the first example; e.g. consider a
   vector<string>. The inside strings are likely to make many small allocation
   requests. If the vector has a scoped allocator that owns it own resources
   (i.e. allocates large chunks of memory), then it can give the strings
   allocators that reference the outer allocator. Again, the same can be
   accomplished with memory pools, but this is cleaner.

My proposal would basically be to change the Allocator concept so that copy
constructability is only necessary if select_on_container_copy_construction is
not defined, or if the allocator uses it internally. In turn,
AllocatorAware would be changed to never make unnecessary copies; which
would also mean changing the standard library. This does not require any
core language changes, and what's more it is backwards compatible. Since it
broadens the definition of legal allocators, all existing allocators would
continue to be allocators and usable in the STL. It would mean that
technically, user written AllocatorAware containers would not be strictly
compliant, but they would keep working with std::allocator (which is
copyable of course) and any allocators they had written themselves.

Thoughts and criticism welcome!

--

---
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 https://groups.google.com/a/isocpp.org/group/std-proposals/.

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

<div dir=3D"ltr"><font size=3D"2">Currently, allocators seem to be absolute=
ly required to be copy constructable. This is actually a very stringent req=
uirement; the copy constructed allocator must compare equal to the original=
 allocator, which for allocators implies that they can allocate and dealloc=
ate each other&#39;s pointers. This is fine if your allocators simply hold =
pointers back to a memory pool. But what if your allocators want to own the=
ir own resources? Such allocators can never really allocate or deallocate e=
ach other&#39;s pointers, so they can never compare equal. This sounds like=
 a big deal, but if your allocator is uncopyable, then it&#39;s not an issu=
e; there&#39;s no real situation where you would ever necessarily expect th=
em to compare equal. The current requirement of copyability is artificial t=
hough, all of the tools are already in place to avoid it. An allocator that=
=C2=A0sets=C2=A0<span style=3D"color: rgb(0, 0, 0); font-family: DejaVuSans=
Mono, &#39;DejaVu Sans Mono&#39;, courier, monospace; white-space: nowrap; =
background-color: rgba(0, 0, 0, 0.027451);">propagate_on_container_copy_ass=
ignment=C2=A0</span>to false=C2=A0 already doesn&#39;t need to be copy assi=
gnable. And if an allocator defines=C2=A0<span style=3D"color: rgb(0, 0, 0)=
; font-family: DejaVuSansMono, &#39;DejaVu Sans Mono&#39;, courier, monospa=
ce; white-space: nowrap; background-color: rgba(0, 0, 0, 0.027451);">select=
_on_container_copy_construction=C2=A0</span>it is never &quot;conceptually&=
quot; copied. Consider the following example:</font><div><font size=3D"2"><=
br></font></div><div><div><font size=3D"2">#include &lt;vector&gt;</font></=
div><div><font size=3D"2">#include &lt;iostream&gt;</font></div><div><font =
size=3D"2"><br></font></div><div><font size=3D"2">template &lt;class T&gt;<=
/font></div><div><font size=3D"2">struct SimpleAllocator {</font></div><div=
><font size=3D"2">=C2=A0 typedef T value_type;</font></div><div><font size=
=3D"2">=C2=A0 SimpleAllocator() =3D default;</font></div><div><font size=3D=
"2">=C2=A0 template &lt;class U&gt; SimpleAllocator(const SimpleAllocator&l=
t;U&gt;&amp; other) {};</font></div><div><font size=3D"2">=C2=A0 T* allocat=
e(std::size_t n) { return new T[n]; };</font></div><div><font size=3D"2">=
=C2=A0 void deallocate(T* p, std::size_t n) { delete [] p; };</font></div><=
div><font size=3D"2"><br></font></div><div><font size=3D"2">=C2=A0 SimpleAl=
locator(const SimpleAllocator&amp;) { std::cerr &lt;&lt; &quot;copy\n&quot;=
; };</font></div><div><font size=3D"2">=C2=A0 SimpleAllocator(SimpleAllocat=
or&amp;&amp;) =3D default;</font></div><div><font size=3D"2">=C2=A0 SimpleA=
llocator&amp; operator=3D(const SimpleAllocator&amp;) =3D delete;</font></d=
iv><div><font size=3D"2">=C2=A0 SimpleAllocator&amp; operator=3D(SimpleAllo=
cator&amp;&amp;) =3D default;</font></div><div><font size=3D"2"><br></font>=
</div><div><font size=3D"2">=C2=A0 SimpleAllocator select_on_container_copy=
_construction() const {</font></div><div><font size=3D"2">=C2=A0 =C2=A0 std=
::cerr &lt;&lt; &quot;blah\n&quot;;</font></div><div><font size=3D"2">=C2=
=A0 =C2=A0 return SimpleAllocator{};</font></div><div><font size=3D"2">=C2=
=A0 }</font></div><div><font size=3D"2">};</font></div><div><font size=3D"2=
"><br></font></div><div><font size=3D"2">template &lt;class T, class U&gt;<=
/font></div><div><font size=3D"2">bool operator=3D=3D(const SimpleAllocator=
&lt;T&gt;&amp;, const SimpleAllocator&lt;U&gt;&amp;) { return true; }</font=
></div><div><font size=3D"2">template &lt;class T, class U&gt;</font></div>=
<div><font size=3D"2">bool operator!=3D(const SimpleAllocator&lt;T&gt;&amp;=
, const SimpleAllocator&lt;U&gt;&amp;) { return false; }</font></div><div><=
font size=3D"2"><br></font></div><div><font size=3D"2">int main(int argc, c=
har **argv) {</font></div><div><font size=3D"2">=C2=A0 std::vector&lt;doubl=
e, SimpleAllocator&lt;double&gt;&gt; x{1.0};</font></div><div><font size=3D=
"2">=C2=A0 std::cerr &lt;&lt; x[0] &lt;&lt; &quot;\n&quot;;</font></div><di=
v><font size=3D"2">=C2=A0 auto y =3D x;</font></div><div><font size=3D"2">}=
</font></div></div><div><font size=3D"2"><br></font></div><div><font size=
=3D"2">This example runs and prints:</font></div><div><font size=3D"2"><br>=
</font></div><div><div><font size=3D"2">copy</font></div><div><font size=3D=
"2">1</font></div><div><font size=3D"2">blah</font></div><div><font size=3D=
"2">copy</font></div></div><div><font size=3D"2"><br></font></div><div><fon=
t size=3D"2">So constructing our container, which should simply default con=
struct an allocator, also makes a copy, despite there being no &quot;concep=
tual&quot; copy. When we copy construct, we create a new allocator using se=
lect_on_container_copy_construction, and copy that new allocator, which is =
also unnecessary.</font></div><div><font size=3D"2"><br></font></div><div><=
font size=3D"2">If these unnecessary copies were eliminated, then it would =
actually be quite simple =C2=A0to write allocators that owned their own res=
ources. Such an allocator just needs a default constructor and move/swap, w=
hich is typically =C2=A0These have multiple applications:</font></div><div>=
<ul><li><span style=3D"line-height: normal;"><font size=3D"2">For data stru=
ctures that perform many small allocations (like map and set), such an allo=
cator would allow making some speed vs space trade-offs by chunking up allo=
cations. This can be done in the current framework, but requires introducin=
g a memory pool, which often has separate lifetime, or perhaps is co-owned =
by its allocators via shared_ptr. Using an owning allocator is much simpler=
 and hassle free; it is a drop in replacement with a typedef.</font></span>=
</li><li><span style=3D"line-height: normal;"><font size=3D"2">It allows on=
e to force the small X optimization on any data structure (less efficiently=
, of course). For instance, one could create an allocator that deliberately=
 contains 64 bytes of empty storage. Allocation requests for 64 bytes or le=
ss are served from this buffer, anything larger is sent to the heap. Conven=
ient e.g. for std::function, or std::vector, and easy to customize.</font><=
/span></li><li><span style=3D"line-height: normal;"><font size=3D"2">It has=
 interesting possibilities combined with scoped_allocators. I admit I haven=
&#39;t investigated these in depth, but it seems like it would allow scenar=
ios similar to the first example; e.g. consider a vector&lt;string&gt;. The=
 inside strings are likely to make many small allocation requests. If the v=
ector has a scoped allocator that owns it own resources (i.e. allocates lar=
ge chunks of memory), then it can give the strings allocators that referenc=
e the outer allocator. Again, the same can be accomplished with memory pool=
s, but this is cleaner.</font></span></li></ul><div><font size=3D"2">My pro=
posal would basically be to change the Allocator concept so that copy const=
ructability is only necessary if=C2=A0</font><span style=3D"color: rgb(0, 0=
, 0); font-family: DejaVuSansMono, &#39;DejaVu Sans Mono&#39;, courier, mon=
ospace; font-size: small; white-space: nowrap; background-color: rgba(0, 0,=
 0, 0.027451);">select_on_container_copy_construction</span><span style=3D"=
font-size: small;">=C2=A0is not defined, or if the allocator uses it intern=
ally. In turn, AllocatorAware would be changed to never make unnecessary co=
pies; which would also mean changing the standard library. This does not re=
quire any core language changes, and what&#39;s more it is backwards compat=
ible. Since it broadens the definition of legal allocators, all existing al=
locators would continue to be allocators and usable in the STL. It would me=
an that technically, user written AllocatorAware containers would not be st=
rictly compliant, but they would keep working with std::allocator (which is=
 copyable of course) and any allocators they had written themselves.=C2=A0<=
/span></div><div><font size=3D"2"><br></font></div></div><div><font size=3D=
"2">Thoughts and criticism welcome!</font></div></div>

<p></p>

-- <br />
<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 <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"https://groups.google.com/a/isocpp.org/group=
/std-proposals/">https://groups.google.com/a/isocpp.org/group/std-proposals=
/</a>.<br />

------=_Part_177_425754619.1452987525462--
------=_Part_176_1034829407.1452987525462--

.


Author: Zhihao Yuan <zy@miator.net>
Date: Sat, 16 Jan 2016 22:12:18 -0600
Raw View
On Sat, Jan 16, 2016 at 5:38 PM,  <quicknir@gmail.com> wrote:
>
>   SimpleAllocator(const SimpleAllocator&) { std::cerr << "copy\n"; };
>   SimpleAllocator(SimpleAllocator&&) = default;
>   SimpleAllocator& operator=(const SimpleAllocator&) = delete;
>   SimpleAllocator& operator=(SimpleAllocator&&) = default;
>
>   SimpleAllocator select_on_container_copy_construction() const {
>     std::cerr << "blah\n";
>     return SimpleAllocator{};
>   }

There won't be any issue after

  http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2015/p0135r0.html

being accepted.

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

--

---
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 https://groups.google.com/a/isocpp.org/group/std-proposals/.

.


Author: quicknir@gmail.com
Date: Sat, 16 Jan 2016 22:36:04 -0800 (PST)
Raw View
------=_Part_3458_1883215125.1453012564714
Content-Type: multipart/alternative;
 boundary="----=_Part_3459_287592463.1453012564714"

------=_Part_3459_287592463.1453012564714
Content-Type: text/plain; charset=UTF-8

While this proposal may make it easier to implement such containers, and
may even cause certain containers of certain standard library types to
happen to work with such an allocator, this is not sufficient. Even if copy
elision is mandatory under certain circumstances, this doesn't change the
fact that a conforming implementation is free to copy around allocators as
much as it wants, because a conforming allocator has to be copy
constructible. Any allocator written in that environment would be
non-portable, which isn't acceptable for many. It's still necessary to
change the definition of a conforming allocator.

This proposal may make it so that the standard library doesn't have to make
any changes to have compliant containers, but that is all, and even that
I'm not certain about. Even without this proposal it is certainly possible
to make things work, though it may be trickier. The proposal in any case
seems to be largely about situations where at least a move can be
guaranteed instead of a copy, it is just that total elision cannot be
guaranteed. In this situation, moving is fine, it's that actual unnecessary
copies are taking place.

Let me know if you feel I've misunderstood.


On Saturday, January 16, 2016 at 11:12:21 PM UTC-5, Zhihao Yuan wrote:
>
> On Sat, Jan 16, 2016 at 5:38 PM,  <quic...@gmail.com <javascript:>>
> wrote:
> >
> >   SimpleAllocator(const SimpleAllocator&) { std::cerr << "copy\n"; };
> >   SimpleAllocator(SimpleAllocator&&) = default;
> >   SimpleAllocator& operator=(const SimpleAllocator&) = delete;
> >   SimpleAllocator& operator=(SimpleAllocator&&) = default;
> >
> >   SimpleAllocator select_on_container_copy_construction() const {
> >     std::cerr << "blah\n";
> >     return SimpleAllocator{};
> >   }
>
> There won't be any issue after
>
>   http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2015/p0135r0.html
>
> being accepted.
>
> --
> Zhihao Yuan, ID lichray
> The best way to predict the future is to invent it.
> ___________________________________________________
> 4BSD -- http://bit.ly/blog4bsd
>

--

---
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 https://groups.google.com/a/isocpp.org/group/std-proposals/.

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

<div dir=3D"ltr"><div>While this proposal may make it easier to implement s=
uch containers, and may even cause certain containers of certain standard l=
ibrary types to happen to work with such an allocator, this is not sufficie=
nt. Even if copy elision is mandatory under certain circumstances, this doe=
sn&#39;t change the fact that a conforming implementation is free to copy a=
round allocators as much as it wants, because a conforming allocator has to=
 be copy constructible. Any allocator written in that environment would be =
non-portable, which isn&#39;t acceptable for many. It&#39;s still necessary=
 to change the definition of a conforming allocator.</div><div><br></div><d=
iv>This proposal may make it so that the standard library doesn&#39;t have =
to make any changes to have compliant containers, but that is all, and even=
 that I&#39;m not certain about. Even without this proposal it is certainly=
 possible to make things work, though it may be trickier. The proposal in a=
ny case seems to be largely about situations where at least a move can be g=
uaranteed instead of a copy, it is just that total elision cannot be guaran=
teed. In this situation, moving is fine, it&#39;s that actual unnecessary c=
opies are taking place.</div><div><br></div><div>Let me know if you feel I&=
#39;ve misunderstood.</div><div><br></div><br>On Saturday, January 16, 2016=
 at 11:12:21 PM UTC-5, Zhihao Yuan wrote:<blockquote class=3D"gmail_quote" =
style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-l=
eft: 1ex;">On Sat, Jan 16, 2016 at 5:38 PM, =C2=A0&lt;<a href=3D"javascript=
:" target=3D"_blank" gdf-obfuscated-mailto=3D"cJYDIGrtFgAJ" rel=3D"nofollow=
" onmousedown=3D"this.href=3D&#39;javascript:&#39;;return true;" onclick=3D=
"this.href=3D&#39;javascript:&#39;;return true;">quic...@gmail.com</a>&gt; =
wrote:
<br>&gt;
<br>&gt; =C2=A0 SimpleAllocator(const SimpleAllocator&amp;) { std::cerr &lt=
;&lt; &quot;copy\n&quot;; };
<br>&gt; =C2=A0 SimpleAllocator(<wbr>SimpleAllocator&amp;&amp;) =3D default=
;
<br>&gt; =C2=A0 SimpleAllocator&amp; operator=3D(const SimpleAllocator&amp;=
) =3D delete;
<br>&gt; =C2=A0 SimpleAllocator&amp; operator=3D(SimpleAllocator&amp;&amp;)=
 =3D default;
<br>&gt;
<br>&gt; =C2=A0 SimpleAllocator select_on_container_copy_<wbr>construction(=
) const {
<br>&gt; =C2=A0 =C2=A0 std::cerr &lt;&lt; &quot;blah\n&quot;;
<br>&gt; =C2=A0 =C2=A0 return SimpleAllocator{};
<br>&gt; =C2=A0 }
<br>
<br>There won&#39;t be any issue after
<br>
<br>=C2=A0 <a href=3D"http://www.open-std.org/JTC1/SC22/WG21/docs/papers/20=
15/p0135r0.html" target=3D"_blank" rel=3D"nofollow" onmousedown=3D"this.hre=
f=3D&#39;http://www.google.com/url?q\75http%3A%2F%2Fwww.open-std.org%2FJTC1=
%2FSC22%2FWG21%2Fdocs%2Fpapers%2F2015%2Fp0135r0.html\46sa\75D\46sntz\0751\4=
6usg\75AFQjCNEvCUGb8SntGH2yWDyjeRZtZwNngA&#39;;return true;" onclick=3D"thi=
s.href=3D&#39;http://www.google.com/url?q\75http%3A%2F%2Fwww.open-std.org%2=
FJTC1%2FSC22%2FWG21%2Fdocs%2Fpapers%2F2015%2Fp0135r0.html\46sa\75D\46sntz\0=
751\46usg\75AFQjCNEvCUGb8SntGH2yWDyjeRZtZwNngA&#39;;return true;">http://ww=
w.open-std.org/JTC1/<wbr>SC22/WG21/docs/papers/2015/<wbr>p0135r0.html</a>
<br>
<br>being accepted.
<br>
<br>--=20
<br>Zhihao Yuan, ID lichray
<br>The best way to predict the future is to invent it.
<br>______________________________<wbr>_____________________
<br>4BSD -- <a href=3D"http://bit.ly/blog4bsd" target=3D"_blank" rel=3D"nof=
ollow" onmousedown=3D"this.href=3D&#39;http://www.google.com/url?q\75http%3=
A%2F%2Fbit.ly%2Fblog4bsd\46sa\75D\46sntz\0751\46usg\75AFQjCNENWZA3DF1H_gEgI=
kwnCr7FAkiCyQ&#39;;return true;" onclick=3D"this.href=3D&#39;http://www.goo=
gle.com/url?q\75http%3A%2F%2Fbit.ly%2Fblog4bsd\46sa\75D\46sntz\0751\46usg\7=
5AFQjCNENWZA3DF1H_gEgIkwnCr7FAkiCyQ&#39;;return true;">http://bit.ly/blog4b=
sd</a>
<br></blockquote></div>

<p></p>

-- <br />
<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 <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"https://groups.google.com/a/isocpp.org/group=
/std-proposals/">https://groups.google.com/a/isocpp.org/group/std-proposals=
/</a>.<br />

------=_Part_3459_287592463.1453012564714--
------=_Part_3458_1883215125.1453012564714--

.


Author: Zhihao Yuan <zy@miator.net>
Date: Sun, 17 Jan 2016 01:38:35 -0600
Raw View
On Sun, Jan 17, 2016 at 12:36 AM,  <quicknir@gmail.com> wrote:
> Even if copy elision is mandatory under certain circumstances, this doesn't
> change the fact that a conforming implementation is free to copy around
> allocators as much as it wants, because a conforming allocator has to be
> copy constructible.

I see where the "problem" is.  But this will require changing all
functions taking a default constructed allocator as const& in the
signatures.

And you need to convince people about why it's useful.
To me, only polymorphic memory resource is useful; other
people may have different opinions.

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

--

---
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 https://groups.google.com/a/isocpp.org/group/std-proposals/.

.


Author: quicknir@gmail.com
Date: Sat, 16 Jan 2016 23:50:04 -0800 (PST)
Raw View
------=_Part_1380_967909574.1453017004963
Content-Type: multipart/alternative;
 boundary="----=_Part_1381_2079785636.1453017004963"

------=_Part_1381_2079785636.1453017004963
Content-Type: text/plain; charset=UTF-8

THat would be one solution, and the preferred one. I don't see a big
problem with taking it by value. Since it is stored by value, slicing is
not an issue. And a copy is being made anyway, passing by value when a copy
is needed is accepted practice. Another solution would be to leave the pass
by const ref but eliminate the default, and then provide additional
overloads that simply construct the allocator internally. This is less
desirable as it will limit uncopyable allocators to default construction.

Not sure what polymorphic means in this context (polymorphic allocator?),
but I did give three use cases. I've literally seen examples of people
rewriting std::function from scratch so that they could change the size of
the small function optimization because heap allocation is a major issue
for them. I've also seen people ask about having a small vector
optimization. Right now, people are forever saddled with the standard
library's decisions when it comes to small object stack optimization, this
seems like something allocators should be able to do. I think my other two
examples are good as well; memory pools are great in many cases, but they
certainly are a hassle, there are both liffetime and threading issues with
them. A chunk allocator for std::map seems like an almost free (minor
memory cost) performance boost.

On Sunday, January 17, 2016 at 2:38:39 AM UTC-5, Zhihao Yuan wrote:
>
> On Sun, Jan 17, 2016 at 12:36 AM,  <quic...@gmail.com <javascript:>>
> wrote:
> > Even if copy elision is mandatory under certain circumstances, this
> doesn't
> > change the fact that a conforming implementation is free to copy around
> > allocators as much as it wants, because a conforming allocator has to be
> > copy constructible.
>
> I see where the "problem" is.  But this will require changing all
> functions taking a default constructed allocator as const& in the
> signatures.
>
> And you need to convince people about why it's useful.
> To me, only polymorphic memory resource is useful; other
> people may have different opinions.
>
> --
> Zhihao Yuan, ID lichray
> The best way to predict the future is to invent it.
> ___________________________________________________
> 4BSD -- http://bit.ly/blog4bsd
>

--

---
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 https://groups.google.com/a/isocpp.org/group/std-proposals/.

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

<div dir=3D"ltr">THat would be one solution, and the preferred one. I don&#=
39;t see a big problem with taking it by value. Since it is stored by value=
, slicing is not an issue. And a copy is being made anyway, passing by valu=
e when a copy is needed is accepted practice. Another solution would be to =
leave the pass by const ref but eliminate the default, and then provide add=
itional overloads that simply construct the allocator internally. This is l=
ess desirable as it will limit uncopyable allocators to default constructio=
n.<div><br></div><div>Not sure what polymorphic means in this context (poly=
morphic allocator?), but I did give three use cases. I&#39;ve literally see=
n examples of people rewriting std::function from scratch so that they coul=
d change the size of the small function optimization because heap allocatio=
n is a major issue for them. I&#39;ve also seen people ask about having a s=
mall vector optimization. Right now, people are forever saddled with the st=
andard library&#39;s decisions when it comes to small object stack optimiza=
tion, this seems like something allocators should be able to do. I think my=
 other two examples are good as well; memory pools are great in many cases,=
 but they certainly are a hassle, there are both liffetime and threading is=
sues with them. A chunk allocator for std::map seems like an almost free (m=
inor memory cost) performance boost.<br><br>On Sunday, January 17, 2016 at =
2:38:39 AM UTC-5, Zhihao Yuan wrote:<blockquote class=3D"gmail_quote" style=
=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: =
1ex;">On Sun, Jan 17, 2016 at 12:36 AM, =C2=A0&lt;<a href=3D"javascript:" t=
arget=3D"_blank" gdf-obfuscated-mailto=3D"Dii-DKz4FgAJ" rel=3D"nofollow" on=
mousedown=3D"this.href=3D&#39;javascript:&#39;;return true;" onclick=3D"thi=
s.href=3D&#39;javascript:&#39;;return true;">quic...@gmail.com</a>&gt; wrot=
e:
<br>&gt; Even if copy elision is mandatory under certain circumstances, thi=
s doesn&#39;t
<br>&gt; change the fact that a conforming implementation is free to copy a=
round
<br>&gt; allocators as much as it wants, because a conforming allocator has=
 to be
<br>&gt; copy constructible.
<br>
<br>I see where the &quot;problem&quot; is. =C2=A0But this will require cha=
nging all
<br>functions taking a default constructed allocator as const&amp; in the
<br>signatures.
<br>
<br>And you need to convince people about why it&#39;s useful.
<br>To me, only polymorphic memory resource is useful; other
<br>people may have different opinions.
<br>
<br>--=20
<br>Zhihao Yuan, ID lichray
<br>The best way to predict the future is to invent it.
<br>______________________________<wbr>_____________________
<br>4BSD -- <a href=3D"http://bit.ly/blog4bsd" target=3D"_blank" rel=3D"nof=
ollow" onmousedown=3D"this.href=3D&#39;http://www.google.com/url?q\75http%3=
A%2F%2Fbit.ly%2Fblog4bsd\46sa\75D\46sntz\0751\46usg\75AFQjCNENWZA3DF1H_gEgI=
kwnCr7FAkiCyQ&#39;;return true;" onclick=3D"this.href=3D&#39;http://www.goo=
gle.com/url?q\75http%3A%2F%2Fbit.ly%2Fblog4bsd\46sa\75D\46sntz\0751\46usg\7=
5AFQjCNENWZA3DF1H_gEgIkwnCr7FAkiCyQ&#39;;return true;">http://bit.ly/blog4b=
sd</a>
<br></blockquote></div></div>

<p></p>

-- <br />
<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 <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"https://groups.google.com/a/isocpp.org/group=
/std-proposals/">https://groups.google.com/a/isocpp.org/group/std-proposals=
/</a>.<br />

------=_Part_1381_2079785636.1453017004963--
------=_Part_1380_967909574.1453017004963--

.


Author: Yun Chen <yun.go.chen@gmail.com>
Date: Sat, 26 Mar 2016 08:44:01 -0700 (PDT)
Raw View
------=_Part_1002_1058651017.1459007041523
Content-Type: multipart/alternative;
 boundary="----=_Part_1003_963224163.1459007041524"

------=_Part_1003_963224163.1459007041524
Content-Type: text/plain; charset=UTF-8

I second the usefulness. Our allocator owns the resource as well and it has
been very painful to tweak STL implementations to do that.

We should extend it to move construction through
select_on_container_move_construction, as we need the ability of default
constructing the allocator too. This would be required to move construct an
container in an arena from stack.


On Saturday, January 16, 2016 at 6:38:45 PM UTC-5, quic...@gmail.com wrote:
>
> Currently, allocators seem to be absolutely required to be copy
> constructable. This is actually a very stringent requirement; the copy
> constructed allocator must compare equal to the original allocator, which
> for allocators implies that they can allocate and deallocate each other's
> pointers. This is fine if your allocators simply hold pointers back to a
> memory pool. But what if your allocators want to own their own resources?
> Such allocators can never really allocate or deallocate each other's
> pointers, so they can never compare equal. This sounds like a big deal, but
> if your allocator is uncopyable, then it's not an issue; there's no real
> situation where you would ever necessarily expect them to compare equal.
> The current requirement of copyability is artificial though, all of the
> tools are already in place to avoid it. An allocator that sets
> propagate_on_container_copy_assignment to false  already doesn't need to
> be copy assignable. And if an allocator defines
> select_on_container_copy_construction it is never "conceptually" copied.
> Consider the following example:
>
> #include <vector>
> #include <iostream>
>
> template <class T>
> struct SimpleAllocator {
>   typedef T value_type;
>   SimpleAllocator() = default;
>   template <class U> SimpleAllocator(const SimpleAllocator<U>& other) {};
>   T* allocate(std::size_t n) { return new T[n]; };
>   void deallocate(T* p, std::size_t n) { delete [] p; };
>
>   SimpleAllocator(const SimpleAllocator&) { std::cerr << "copy\n"; };
>   SimpleAllocator(SimpleAllocator&&) = default;
>   SimpleAllocator& operator=(const SimpleAllocator&) = delete;
>   SimpleAllocator& operator=(SimpleAllocator&&) = default;
>
>   SimpleAllocator select_on_container_copy_construction() const {
>     std::cerr << "blah\n";
>     return SimpleAllocator{};
>   }
> };
>
> template <class T, class U>
> bool operator==(const SimpleAllocator<T>&, const SimpleAllocator<U>&) {
> return true; }
> template <class T, class U>
> bool operator!=(const SimpleAllocator<T>&, const SimpleAllocator<U>&) {
> return false; }
>
> int main(int argc, char **argv) {
>   std::vector<double, SimpleAllocator<double>> x{1.0};
>   std::cerr << x[0] << "\n";
>   auto y = x;
> }
>
> This example runs and prints:
>
> copy
> 1
> blah
> copy
>
> So constructing our container, which should simply default construct an
> allocator, also makes a copy, despite there being no "conceptual" copy.
> When we copy construct, we create a new allocator using
> select_on_container_copy_construction, and copy that new allocator, which
> is also unnecessary.
>
> If these unnecessary copies were eliminated, then it would actually be
> quite simple  to write allocators that owned their own resources. Such an
> allocator just needs a default constructor and move/swap, which is
> typically  These have multiple applications:
>
>    - For data structures that perform many small allocations (like map
>    and set), such an allocator would allow making some speed vs space
>    trade-offs by chunking up allocations. This can be done in the current
>    framework, but requires introducing a memory pool, which often has separate
>    lifetime, or perhaps is co-owned by its allocators via shared_ptr. Using an
>    owning allocator is much simpler and hassle free; it is a drop in
>    replacement with a typedef.
>    - It allows one to force the small X optimization on any data
>    structure (less efficiently, of course). For instance, one could create an
>    allocator that deliberately contains 64 bytes of empty storage. Allocation
>    requests for 64 bytes or less are served from this buffer, anything larger
>    is sent to the heap. Convenient e.g. for std::function, or std::vector, and
>    easy to customize.
>    - It has interesting possibilities combined with scoped_allocators. I
>    admit I haven't investigated these in depth, but it seems like it would
>    allow scenarios similar to the first example; e.g. consider a
>    vector<string>. The inside strings are likely to make many small allocation
>    requests. If the vector has a scoped allocator that owns it own resources
>    (i.e. allocates large chunks of memory), then it can give the strings
>    allocators that reference the outer allocator. Again, the same can be
>    accomplished with memory pools, but this is cleaner.
>
> My proposal would basically be to change the Allocator concept so that
> copy constructability is only necessary if
> select_on_container_copy_construction is not defined, or if the allocator
> uses it internally. In turn, AllocatorAware would be changed to never make
> unnecessary copies; which would also mean changing the standard library.
> This does not require any core language changes, and what's more it is
> backwards compatible. Since it broadens the definition of legal allocators,
> all existing allocators would continue to be allocators and usable in the
> STL. It would mean that technically, user written AllocatorAware containers
> would not be strictly compliant, but they would keep working with
> std::allocator (which is copyable of course) and any allocators they had
> written themselves.
>
> Thoughts and criticism welcome!
>

--
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.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/8a887b00-e400-4f63-8a66-c947448880d9%40isocpp.org.

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

<div dir=3D"ltr"><div>I second the usefulness. Our allocator owns the resou=
rce as well and it has been very painful to tweak STL implementations to do=
 that.</div><div><br></div><div>We should extend it to move construction th=
rough select_on_container_move_construction, as we need the ability of defa=
ult constructing the allocator too. This would be required to move construc=
t an container in an arena from stack. =C2=A0</div><div><br></div><br>On Sa=
turday, January 16, 2016 at 6:38:45 PM UTC-5, quic...@gmail.com wrote:<bloc=
kquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-l=
eft: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><font size=3D"2">C=
urrently, allocators seem to be absolutely required to be copy constructabl=
e. This is actually a very stringent requirement; the copy constructed allo=
cator must compare equal to the original allocator, which for allocators im=
plies that they can allocate and deallocate each other&#39;s pointers. This=
 is fine if your allocators simply hold pointers back to a memory pool. But=
 what if your allocators want to own their own resources? Such allocators c=
an never really allocate or deallocate each other&#39;s pointers, so they c=
an never compare equal. This sounds like a big deal, but if your allocator =
is uncopyable, then it&#39;s not an issue; there&#39;s no real situation wh=
ere you would ever necessarily expect them to compare equal. The current re=
quirement of copyability is artificial though, all of the tools are already=
 in place to avoid it. An allocator that=C2=A0sets=C2=A0<span style=3D"colo=
r:rgb(0,0,0);font-family:DejaVuSansMono,&#39;DejaVu Sans Mono&#39;,courier,=
monospace;white-space:nowrap;background-color:rgba(0,0,0,0.027451)">propaga=
te_on_<wbr>container_copy_assignment=C2=A0</span>to false=C2=A0 already doe=
sn&#39;t need to be copy assignable. And if an allocator defines=C2=A0<span=
 style=3D"color:rgb(0,0,0);font-family:DejaVuSansMono,&#39;DejaVu Sans Mono=
&#39;,courier,monospace;white-space:nowrap;background-color:rgba(0,0,0,0.02=
7451)">select_on_container_<wbr>copy_construction=C2=A0</span>it is never &=
quot;conceptually&quot; copied. Consider the following example:</font><div>=
<font size=3D"2"><br></font></div><div><div><font size=3D"2">#include &lt;v=
ector&gt;</font></div><div><font size=3D"2">#include &lt;iostream&gt;</font=
></div><div><font size=3D"2"><br></font></div><div><font size=3D"2">templat=
e &lt;class T&gt;</font></div><div><font size=3D"2">struct SimpleAllocator =
{</font></div><div><font size=3D"2">=C2=A0 typedef T value_type;</font></di=
v><div><font size=3D"2">=C2=A0 SimpleAllocator() =3D default;</font></div><=
div><font size=3D"2">=C2=A0 template &lt;class U&gt; SimpleAllocator(const =
SimpleAllocator&lt;U&gt;&amp; other) {};</font></div><div><font size=3D"2">=
=C2=A0 T* allocate(std::size_t n) { return new T[n]; };</font></div><div><f=
ont size=3D"2">=C2=A0 void deallocate(T* p, std::size_t n) { delete [] p; }=
;</font></div><div><font size=3D"2"><br></font></div><div><font size=3D"2">=
=C2=A0 SimpleAllocator(const SimpleAllocator&amp;) { std::cerr &lt;&lt; &qu=
ot;copy\n&quot;; };</font></div><div><font size=3D"2">=C2=A0 SimpleAllocato=
r(<wbr>SimpleAllocator&amp;&amp;) =3D default;</font></div><div><font size=
=3D"2">=C2=A0 SimpleAllocator&amp; operator=3D(const SimpleAllocator&amp;) =
=3D delete;</font></div><div><font size=3D"2">=C2=A0 SimpleAllocator&amp; o=
perator=3D(SimpleAllocator&amp;&amp;) =3D default;</font></div><div><font s=
ize=3D"2"><br></font></div><div><font size=3D"2">=C2=A0 SimpleAllocator sel=
ect_on_container_copy_<wbr>construction() const {</font></div><div><font si=
ze=3D"2">=C2=A0 =C2=A0 std::cerr &lt;&lt; &quot;blah\n&quot;;</font></div><=
div><font size=3D"2">=C2=A0 =C2=A0 return SimpleAllocator{};</font></div><d=
iv><font size=3D"2">=C2=A0 }</font></div><div><font size=3D"2">};</font></d=
iv><div><font size=3D"2"><br></font></div><div><font size=3D"2">template &l=
t;class T, class U&gt;</font></div><div><font size=3D"2">bool operator=3D=
=3D(const SimpleAllocator&lt;T&gt;&amp;, const SimpleAllocator&lt;U&gt;&amp=
;) { return true; }</font></div><div><font size=3D"2">template &lt;class T,=
 class U&gt;</font></div><div><font size=3D"2">bool operator!=3D(const Simp=
leAllocator&lt;T&gt;&amp;, const SimpleAllocator&lt;U&gt;&amp;) { return fa=
lse; }</font></div><div><font size=3D"2"><br></font></div><div><font size=
=3D"2">int main(int argc, char **argv) {</font></div><div><font size=3D"2">=
=C2=A0 std::vector&lt;double, SimpleAllocator&lt;double&gt;&gt; x{1.0};</fo=
nt></div><div><font size=3D"2">=C2=A0 std::cerr &lt;&lt; x[0] &lt;&lt; &quo=
t;\n&quot;;</font></div><div><font size=3D"2">=C2=A0 auto y =3D x;</font></=
div><div><font size=3D"2">}</font></div></div><div><font size=3D"2"><br></f=
ont></div><div><font size=3D"2">This example runs and prints:</font></div><=
div><font size=3D"2"><br></font></div><div><div><font size=3D"2">copy</font=
></div><div><font size=3D"2">1</font></div><div><font size=3D"2">blah</font=
></div><div><font size=3D"2">copy</font></div></div><div><font size=3D"2"><=
br></font></div><div><font size=3D"2">So constructing our container, which =
should simply default construct an allocator, also makes a copy, despite th=
ere being no &quot;conceptual&quot; copy. When we copy construct, we create=
 a new allocator using select_on_container_copy_<wbr>construction, and copy=
 that new allocator, which is also unnecessary.</font></div><div><font size=
=3D"2"><br></font></div><div><font size=3D"2">If these unnecessary copies w=
ere eliminated, then it would actually be quite simple =C2=A0to write alloc=
ators that owned their own resources. Such an allocator just needs a defaul=
t constructor and move/swap, which is typically =C2=A0These have multiple a=
pplications:</font></div><div><ul><li><span style=3D"line-height:normal"><f=
ont size=3D"2">For data structures that perform many small allocations (lik=
e map and set), such an allocator would allow making some speed vs space tr=
ade-offs by chunking up allocations. This can be done in the current framew=
ork, but requires introducing a memory pool, which often has separate lifet=
ime, or perhaps is co-owned by its allocators via shared_ptr. Using an owni=
ng allocator is much simpler and hassle free; it is a drop in replacement w=
ith a typedef.</font></span></li><li><span style=3D"line-height:normal"><fo=
nt size=3D"2">It allows one to force the small X optimization on any data s=
tructure (less efficiently, of course). For instance, one could create an a=
llocator that deliberately contains 64 bytes of empty storage. Allocation r=
equests for 64 bytes or less are served from this buffer, anything larger i=
s sent to the heap. Convenient e.g. for std::function, or std::vector, and =
easy to customize.</font></span></li><li><span style=3D"line-height:normal"=
><font size=3D"2">It has interesting possibilities combined with scoped_all=
ocators. I admit I haven&#39;t investigated these in depth, but it seems li=
ke it would allow scenarios similar to the first example; e.g. consider a v=
ector&lt;string&gt;. The inside strings are likely to make many small alloc=
ation requests. If the vector has a scoped allocator that owns it own resou=
rces (i.e. allocates large chunks of memory), then it can give the strings =
allocators that reference the outer allocator. Again, the same can be accom=
plished with memory pools, but this is cleaner.</font></span></li></ul><div=
><font size=3D"2">My proposal would basically be to change the Allocator co=
ncept so that copy constructability is only necessary if=C2=A0</font><span =
style=3D"color:rgb(0,0,0);font-family:DejaVuSansMono,&#39;DejaVu Sans Mono&=
#39;,courier,monospace;font-size:small;white-space:nowrap;background-color:=
rgba(0,0,0,0.027451)">select_on_container_copy_<wbr>construction</span><spa=
n style=3D"font-size:small">=C2=A0is not defined, or if the allocator uses =
it internally. In turn, AllocatorAware would be changed to never make unnec=
essary copies; which would also mean changing the standard library. This do=
es not require any core language changes, and what&#39;s more it is backwar=
ds compatible. Since it broadens the definition of legal allocators, all ex=
isting allocators would continue to be allocators and usable in the STL. It=
 would mean that technically, user written AllocatorAware containers would =
not be strictly compliant, but they would keep working with std::allocator =
(which is copyable of course) and any allocators they had written themselve=
s.=C2=A0</span></div><div><font size=3D"2"><br></font></div></div><div><fon=
t size=3D"2">Thoughts and criticism welcome!</font></div></div></blockquote=
></div>

<p></p>

-- <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 <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/8a887b00-e400-4f63-8a66-c947448880d9%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/8a887b00-e400-4f63-8a66-c947448880d9=
%40isocpp.org</a>.<br />

------=_Part_1003_963224163.1459007041524--
------=_Part_1002_1058651017.1459007041523--

.


Author: David Krauss <potswa@gmail.com>
Date: Sun, 27 Mar 2016 00:59:06 +0800
Raw View
--Apple-Mail=_BA5DEE2C-01DA-445B-B5C1-7F78B7413E42
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8


> On 2016=E2=80=9301=E2=80=9317, at 7:38 AM, quicknir@gmail.com wrote:
>=20
> But what if your allocators want to own their own resources? Such allocat=
ors can never really allocate or deallocate each other's pointers, so they =
can never compare equal. This sounds like a big deal, but if your allocator=
 is uncopyable, then it's not an issue; there's no real situation where you=
 would ever necessarily expect them to compare equal.

It would be nice to see this avenue pursued. It would allow =E2=80=9Csmall=
=E2=80=9D or =E2=80=9Clocal=E2=80=9D vectors to be specializations of std::=
vector. Locally-optimized versions of all the standard containers would app=
ear for minimal effort.


> On 2016=E2=80=9301=E2=80=9317, at 12:12 PM, Zhihao Yuan <zy@miator.net> w=
rote:
>=20
> There won't be any issue after
>=20
>  http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2015/p0135r0.html
>=20
> being accepted.

The interface for initializing and retrieving the internal allocator would =
need to be revised, at least for the new local allocators. It would be nice=
 to even remove it, but querying the remaining capacity is too useful.

(Regarding =E2=80=9Cnever equal,=E2=80=9D pedantically, if you can obtain a=
 reference to a local allocator, then it should compare equal to itself.)


> On 2016=E2=80=9301=E2=80=9317, at 3:50 PM, quicknir@gmail.com wrote:
>=20
> Not sure what polymorphic means in this context (polymorphic allocator?),

Polymorphic allocators exist on the opposite end of the overall problem dom=
ain of allocators. Every allocator object gets reduced to a polymorphic poi=
nter, and every allocation and deallocation is dispatched as a virtual func=
tion. This helps interoperability at the expense of performance. It=E2=80=
=99s part of the Fundamentals TS; it may or may not be adopted by C++17.

> I've literally seen examples of people rewriting std::function from scrat=
ch so that they could change the size of the small function optimization be=
cause heap allocation is a major issue for them.

This seems to be fairly common. Unfortunately, the small function optimizat=
ion takes place outside the allocator. You could perhaps hack a local alloc=
ator into my function_container <https://github.com/potswa/cxx_function> te=
mplate. But you=E2=80=99d want to forbid converting that back to an ordinar=
y function, or else do something clever like heap-allocate the local alloca=
tor. The library doesn=E2=80=99t provide for that. Also, the ordinary small=
-function optimization would be made redundant=E2=80=A6 it=E2=80=99s possib=
le that this is an entirely different problem.


> On 2016=E2=80=9303=E2=80=9326, at 11:44 PM, Yun Chen <yun.go.chen@gmail.c=
om> wrote:
>=20
> We should extend it to move construction through select_on_container_move=
_construction, as we need the ability of default constructing the allocator=
 too. This would be required to move construct an container in an arena fro=
m stack. =20

=E2=80=A6 and lest it be overlooked, if these allocators aren=E2=80=99t cop=
yable, they=E2=80=99re not movable either.

--=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.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/C2CA1C21-42FC-448F-BCEE-F6B4F3EA8E55%40gmail.com=
..

--Apple-Mail=_BA5DEE2C-01DA-445B-B5C1-7F78B7413E42
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8

<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dutf-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: s=
pace; -webkit-line-break: after-white-space;" class=3D""><div class=3D""><b=
r class=3D""></div><blockquote type=3D"cite" class=3D""><div class=3D"">On =
2016=E2=80=9301=E2=80=9317, at 7:38 AM, <a href=3D"mailto:quicknir@gmail.co=
m" class=3D"">quicknir@gmail.com</a> wrote:</div><br class=3D"Apple-interch=
ange-newline"><div class=3D""><span class=3D"" style=3D"float: none; displa=
y: inline !important;">But what if your allocators want to own their own re=
sources? Such allocators can never really allocate or deallocate each other=
's pointers, so they can never compare equal. This sounds like a big deal, =
but if your allocator is uncopyable, then it's not an issue; there's no rea=
l situation where you would ever necessarily expect them to compare equal.<=
/span></div></blockquote><div class=3D""><div class=3D""><span class=3D"" s=
tyle=3D"float: none; display: inline !important;"><br class=3D""></span></d=
iv></div><div class=3D""><span class=3D"" style=3D"float: none; display: in=
line !important;">It would be nice to see this avenue pursued. It would all=
ow =E2=80=9Csmall=E2=80=9D or =E2=80=9Clocal=E2=80=9D vectors to be special=
izations of <font face=3D"Courier" class=3D"">std::vector</font>. Locally-o=
ptimized versions of all the standard containers would appear for minimal e=
ffort.</span></div><div class=3D""><br class=3D""></div><div class=3D""><sp=
an class=3D"" style=3D"font-size: small; float: none; display: inline !impo=
rtant;"><br class=3D""></span></div><div><blockquote type=3D"cite" class=3D=
""><div class=3D"">On 2016=E2=80=9301=E2=80=9317, at 12:12 PM, Zhihao Yuan =
&lt;<a href=3D"mailto:zy@miator.net" class=3D"">zy@miator.net</a>&gt; wrote=
:</div><br class=3D"Apple-interchange-newline"><div class=3D""><div class=
=3D"">There won't be any issue after<br class=3D""><br class=3D""> &nbsp;<a=
 href=3D"http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2015/p0135r0.ht=
ml" class=3D"">http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2015/p013=
5r0.html</a><br class=3D""><br class=3D"">being accepted.<br class=3D""></d=
iv></div></blockquote></div><br class=3D""><div class=3D"">The interface fo=
r initializing and retrieving the internal allocator would need to be revis=
ed, at least for the new local allocators. It would be nice to even remove =
it, but querying the remaining capacity is too useful.</div><div class=3D""=
><br class=3D""></div><div class=3D"">(Regarding =E2=80=9Cnever equal,=E2=
=80=9D pedantically, if you can obtain a reference to a local allocator, th=
en it should compare equal to itself.)</div><div class=3D""><br class=3D"">=
</div><div class=3D""><br class=3D""></div><div class=3D""><blockquote type=
=3D"cite" class=3D"">On 2016=E2=80=9301=E2=80=9317, at 3:50 PM, <a href=3D"=
mailto:quicknir@gmail.com" class=3D"">quicknir@gmail.com</a> wrote:</blockq=
uote><blockquote type=3D"cite"><br class=3D"Apple-interchange-newline"><div=
 class=3D""></div></blockquote><blockquote type=3D"cite" class=3D""><div cl=
ass=3D""><span class=3D"" style=3D"float: none; display: inline !important;=
">Not sure what polymorphic means in this context (polymorphic allocator?),=
</span></div></blockquote><div class=3D""><br class=3D""></div><div class=
=3D"">Polymorphic allocators exist on the opposite end of the overall probl=
em domain of allocators. Every allocator object gets reduced to a polymorph=
ic pointer, and every allocation and deallocation is dispatched as a virtua=
l function. This helps interoperability at the expense of performance. It=
=E2=80=99s part of the Fundamentals TS; it may or may not be adopted by C++=
17.</div><br class=3D""><blockquote type=3D"cite" class=3D""><div class=3D"=
"><span class=3D"" style=3D"float: none; display: inline !important;"> I've=
 literally seen examples of people rewriting std::function from scratch so =
that they could change the size of the small function optimization because =
heap allocation is a major issue for them.</span></div></blockquote><br cla=
ss=3D""></div><div class=3D"">This seems to be fairly common. Unfortunately=
, the small function optimization takes place outside the allocator. You co=
uld perhaps hack a local allocator into my&nbsp;<a href=3D"https://github.c=
om/potswa/cxx_function" class=3D""><font face=3D"Courier" class=3D"">functi=
on_container</font></a>&nbsp;template. But you=E2=80=99d want to forbid con=
verting that back to an ordinary <font face=3D"Courier" class=3D"">function=
</font>, or else do something clever like heap-allocate the local allocator=
.. The library doesn=E2=80=99t provide for that. Also, the ordinary small-fu=
nction optimization would be made redundant=E2=80=A6 it=E2=80=99s possible =
that this is an entirely different problem.</div><div class=3D""><br class=
=3D""></div><div class=3D""><br class=3D""></div><div class=3D""><blockquot=
e type=3D"cite" class=3D""><div class=3D"">On 2016=E2=80=9303=E2=80=9326, a=
t 11:44 PM, Yun Chen &lt;<a href=3D"mailto:yun.go.chen@gmail.com" class=3D"=
">yun.go.chen@gmail.com</a>&gt; wrote:</div><br class=3D"Apple-interchange-=
newline"><div class=3D""><div class=3D"">We should extend it to move constr=
uction through select_on_container_move_construction, as we need the abilit=
y of default constructing the allocator too. This would be required to move=
 construct an container in an arena from stack. &nbsp;</div></div></blockqu=
ote><br class=3D""></div><div class=3D"">=E2=80=A6 and lest it be overlooke=
d, if these allocators aren=E2=80=99t copyable, they=E2=80=99re not movable=
 either.</div><div class=3D""><br class=3D""></div></body></html>

<p></p>

-- <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 <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/C2CA1C21-42FC-448F-BCEE-F6B4F3EA8E55%=
40gmail.com?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/C2CA1C21-42FC-448F-BCEE-F6B4F3EA8E55%=
40gmail.com</a>.<br />

--Apple-Mail=_BA5DEE2C-01DA-445B-B5C1-7F78B7413E42--

.


Author: quicknir@gmail.com
Date: Tue, 29 Mar 2016 07:42:54 -0700 (PDT)
Raw View
------=_Part_5522_1515053557.1459262574756
Content-Type: multipart/alternative;
 boundary="----=_Part_5523_1702318432.1459262574757"

------=_Part_5523_1702318432.1459262574757
Content-Type: text/plain; charset=UTF-8

That is a good point. Currently, from what I can see, containers purely
assume that they can "take ownership" of existing elements on move
construction. This means that the container never calls copy or move
constructors on individual elements during container move construction.
It's worth being aware though that select_on_container_move_construction is
actually more complex than any of the existing traits. The
select_on_..._copy equivalent is simply a function that's called to get the
new allocator (which, if not provided, calls the allocator copy
constructor), after which the elements are copied over; there's no
branching per se. The other traits (propagate_on{copy/move_assignment,
swap}) are simply booleans, if they are true than the allocator is
propagated, if not then it isn't. Here, there's a bit of a mixture of both
logic: if select_on_...move_ is defined, then the container should call it,
and then call the move constructor for each element individually. If it is
not defined, then it should move the allocator and do nothing else.

It's getting to the point where it might just be preferable for allocators
to have an "is_movable" trait, since generally select_on_...move, propagate
on move, propagate on swap are all very closely related. But it's unlikely
such a major change could be accepted.

On Saturday, March 26, 2016 at 11:44:01 AM UTC-4, Yun Chen wrote:
>
> I second the usefulness. Our allocator owns the resource as well and it
> has been very painful to tweak STL implementations to do that.
>
> We should extend it to move construction through
> select_on_container_move_construction, as we need the ability of default
> constructing the allocator too. This would be required to move construct an
> container in an arena from stack.
>
>
> On Saturday, January 16, 2016 at 6:38:45 PM UTC-5, quic...@gmail.com
> wrote:
>>
>> Currently, allocators seem to be absolutely required to be copy
>> constructable. This is actually a very stringent requirement; the copy
>> constructed allocator must compare equal to the original allocator, which
>> for allocators implies that they can allocate and deallocate each other's
>> pointers. This is fine if your allocators simply hold pointers back to a
>> memory pool. But what if your allocators want to own their own resources?
>> Such allocators can never really allocate or deallocate each other's
>> pointers, so they can never compare equal. This sounds like a big deal, but
>> if your allocator is uncopyable, then it's not an issue; there's no real
>> situation where you would ever necessarily expect them to compare equal.
>> The current requirement of copyability is artificial though, all of the
>> tools are already in place to avoid it. An allocator that sets
>> propagate_on_container_copy_assignment to false  already doesn't need to
>> be copy assignable. And if an allocator defines
>> select_on_container_copy_construction it is never "conceptually" copied.
>> Consider the following example:
>>
>> #include <vector>
>> #include <iostream>
>>
>> template <class T>
>> struct SimpleAllocator {
>>   typedef T value_type;
>>   SimpleAllocator() = default;
>>   template <class U> SimpleAllocator(const SimpleAllocator<U>& other) {};
>>   T* allocate(std::size_t n) { return new T[n]; };
>>   void deallocate(T* p, std::size_t n) { delete [] p; };
>>
>>   SimpleAllocator(const SimpleAllocator&) { std::cerr << "copy\n"; };
>>   SimpleAllocator(SimpleAllocator&&) = default;
>>   SimpleAllocator& operator=(const SimpleAllocator&) = delete;
>>   SimpleAllocator& operator=(SimpleAllocator&&) = default;
>>
>>   SimpleAllocator select_on_container_copy_construction() const {
>>     std::cerr << "blah\n";
>>     return SimpleAllocator{};
>>   }
>> };
>>
>> template <class T, class U>
>> bool operator==(const SimpleAllocator<T>&, const SimpleAllocator<U>&) {
>> return true; }
>> template <class T, class U>
>> bool operator!=(const SimpleAllocator<T>&, const SimpleAllocator<U>&) {
>> return false; }
>>
>> int main(int argc, char **argv) {
>>   std::vector<double, SimpleAllocator<double>> x{1.0};
>>   std::cerr << x[0] << "\n";
>>   auto y = x;
>> }
>>
>> This example runs and prints:
>>
>> copy
>> 1
>> blah
>> copy
>>
>> So constructing our container, which should simply default construct an
>> allocator, also makes a copy, despite there being no "conceptual" copy.
>> When we copy construct, we create a new allocator using
>> select_on_container_copy_construction, and copy that new allocator, which
>> is also unnecessary.
>>
>> If these unnecessary copies were eliminated, then it would actually be
>> quite simple  to write allocators that owned their own resources. Such an
>> allocator just needs a default constructor and move/swap, which is
>> typically  These have multiple applications:
>>
>>    - For data structures that perform many small allocations (like map
>>    and set), such an allocator would allow making some speed vs space
>>    trade-offs by chunking up allocations. This can be done in the current
>>    framework, but requires introducing a memory pool, which often has separate
>>    lifetime, or perhaps is co-owned by its allocators via shared_ptr. Using an
>>    owning allocator is much simpler and hassle free; it is a drop in
>>    replacement with a typedef.
>>    - It allows one to force the small X optimization on any data
>>    structure (less efficiently, of course). For instance, one could create an
>>    allocator that deliberately contains 64 bytes of empty storage. Allocation
>>    requests for 64 bytes or less are served from this buffer, anything larger
>>    is sent to the heap. Convenient e.g. for std::function, or std::vector, and
>>    easy to customize.
>>    - It has interesting possibilities combined with scoped_allocators. I
>>    admit I haven't investigated these in depth, but it seems like it would
>>    allow scenarios similar to the first example; e.g. consider a
>>    vector<string>. The inside strings are likely to make many small allocation
>>    requests. If the vector has a scoped allocator that owns it own resources
>>    (i.e. allocates large chunks of memory), then it can give the strings
>>    allocators that reference the outer allocator. Again, the same can be
>>    accomplished with memory pools, but this is cleaner.
>>
>> My proposal would basically be to change the Allocator concept so that
>> copy constructability is only necessary if
>> select_on_container_copy_construction is not defined, or if the
>> allocator uses it internally. In turn, AllocatorAware would be changed to
>> never make unnecessary copies; which would also mean changing the standard
>> library. This does not require any core language changes, and what's more
>> it is backwards compatible. Since it broadens the definition of legal
>> allocators, all existing allocators would continue to be allocators and
>> usable in the STL. It would mean that technically, user written
>> AllocatorAware containers would not be strictly compliant, but they would
>> keep working with std::allocator (which is copyable of course) and any
>> allocators they had written themselves.
>>
>> Thoughts and criticism welcome!
>>
>

--
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.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/33f9bac7-4b88-4620-b3c7-ed914f93299a%40isocpp.org.

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

<div dir=3D"ltr"><div>That is a good point. Currently, from what I can see,=
 containers purely assume that they can &quot;take ownership&quot; of exist=
ing elements on move construction. This means that the container never call=
s copy or move constructors on individual elements during container move co=
nstruction. It&#39;s worth being aware though that select_on_container_move=
_construction is actually more complex than any of the existing traits. The=
 select_on_..._copy equivalent is simply a function that&#39;s called to ge=
t the new allocator (which, if not provided, calls the allocator copy const=
ructor), after which the elements are copied over; there&#39;s no branching=
 per se. The other traits (propagate_on{copy/move_assignment, swap}) are si=
mply booleans, if they are true than the allocator is propagated, if not th=
en it isn&#39;t. Here, there&#39;s a bit of a mixture of both logic: if sel=
ect_on_...move_ is defined, then the container should call it, and then cal=
l the move constructor for each element individually. If it is not defined,=
 then it should move the allocator and do nothing else.</div><div><br></div=
><div>It&#39;s getting to the point where it might just be preferable for a=
llocators to have an &quot;is_movable&quot; trait, since generally select_o=
n_...move, propagate on move, propagate on swap are all very closely relate=
d. But it&#39;s unlikely such a major change could be accepted.</div><br>On=
 Saturday, March 26, 2016 at 11:44:01 AM UTC-4, Yun Chen wrote:<blockquote =
class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1p=
x #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div>I second the usefuln=
ess. Our allocator owns the resource as well and it has been very painful t=
o tweak STL implementations to do that.</div><div><br></div><div>We should =
extend it to move construction through select_on_container_move_<wbr>constr=
uction, as we need the ability of default constructing the allocator too. T=
his would be required to move construct an container in an arena from stack=
.. =C2=A0</div><div><br></div><br>On Saturday, January 16, 2016 at 6:38:45 P=
M UTC-5, <a>quic...@gmail.com</a> wrote:<blockquote class=3D"gmail_quote" s=
tyle=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:=
1ex"><div dir=3D"ltr"><font size=3D"2">Currently, allocators seem to be abs=
olutely required to be copy constructable. This is actually a very stringen=
t requirement; the copy constructed allocator must compare equal to the ori=
ginal allocator, which for allocators implies that they can allocate and de=
allocate each other&#39;s pointers. This is fine if your allocators simply =
hold pointers back to a memory pool. But what if your allocators want to ow=
n their own resources? Such allocators can never really allocate or dealloc=
ate each other&#39;s pointers, so they can never compare equal. This sounds=
 like a big deal, but if your allocator is uncopyable, then it&#39;s not an=
 issue; there&#39;s no real situation where you would ever necessarily expe=
ct them to compare equal. The current requirement of copyability is artific=
ial though, all of the tools are already in place to avoid it. An allocator=
 that=C2=A0sets=C2=A0<span style=3D"color:rgb(0,0,0);font-family:DejaVuSans=
Mono,&#39;DejaVu Sans Mono&#39;,courier,monospace;white-space:nowrap;backgr=
ound-color:rgba(0,0,0,0.027451)">propagate_on_<wbr>container_copy_assignmen=
t=C2=A0</span>to false=C2=A0 already doesn&#39;t need to be copy assignable=
.. And if an allocator defines=C2=A0<span style=3D"color:rgb(0,0,0);font-fam=
ily:DejaVuSansMono,&#39;DejaVu Sans Mono&#39;,courier,monospace;white-space=
:nowrap;background-color:rgba(0,0,0,0.027451)">select_on_container_<wbr>cop=
y_construction=C2=A0</span>it is never &quot;conceptually&quot; copied. Con=
sider the following example:</font><div><font size=3D"2"><br></font></div><=
div><div><font size=3D"2">#include &lt;vector&gt;</font></div><div><font si=
ze=3D"2">#include &lt;iostream&gt;</font></div><div><font size=3D"2"><br></=
font></div><div><font size=3D"2">template &lt;class T&gt;</font></div><div>=
<font size=3D"2">struct SimpleAllocator {</font></div><div><font size=3D"2"=
>=C2=A0 typedef T value_type;</font></div><div><font size=3D"2">=C2=A0 Simp=
leAllocator() =3D default;</font></div><div><font size=3D"2">=C2=A0 templat=
e &lt;class U&gt; SimpleAllocator(const SimpleAllocator&lt;U&gt;&amp; other=
) {};</font></div><div><font size=3D"2">=C2=A0 T* allocate(std::size_t n) {=
 return new T[n]; };</font></div><div><font size=3D"2">=C2=A0 void dealloca=
te(T* p, std::size_t n) { delete [] p; };</font></div><div><font size=3D"2"=
><br></font></div><div><font size=3D"2">=C2=A0 SimpleAllocator(const Simple=
Allocator&amp;) { std::cerr &lt;&lt; &quot;copy\n&quot;; };</font></div><di=
v><font size=3D"2">=C2=A0 SimpleAllocator(<wbr>SimpleAllocator&amp;&amp;) =
=3D default;</font></div><div><font size=3D"2">=C2=A0 SimpleAllocator&amp; =
operator=3D(const SimpleAllocator&amp;) =3D delete;</font></div><div><font =
size=3D"2">=C2=A0 SimpleAllocator&amp; operator=3D(SimpleAllocator&amp;&amp=
;) =3D default;</font></div><div><font size=3D"2"><br></font></div><div><fo=
nt size=3D"2">=C2=A0 SimpleAllocator select_on_container_copy_<wbr>construc=
tion() const {</font></div><div><font size=3D"2">=C2=A0 =C2=A0 std::cerr &l=
t;&lt; &quot;blah\n&quot;;</font></div><div><font size=3D"2">=C2=A0 =C2=A0 =
return SimpleAllocator{};</font></div><div><font size=3D"2">=C2=A0 }</font>=
</div><div><font size=3D"2">};</font></div><div><font size=3D"2"><br></font=
></div><div><font size=3D"2">template &lt;class T, class U&gt;</font></div>=
<div><font size=3D"2">bool operator=3D=3D(const SimpleAllocator&lt;T&gt;&am=
p;, const SimpleAllocator&lt;U&gt;&amp;) { return true; }</font></div><div>=
<font size=3D"2">template &lt;class T, class U&gt;</font></div><div><font s=
ize=3D"2">bool operator!=3D(const SimpleAllocator&lt;T&gt;&amp;, const Simp=
leAllocator&lt;U&gt;&amp;) { return false; }</font></div><div><font size=3D=
"2"><br></font></div><div><font size=3D"2">int main(int argc, char **argv) =
{</font></div><div><font size=3D"2">=C2=A0 std::vector&lt;double, SimpleAll=
ocator&lt;double&gt;&gt; x{1.0};</font></div><div><font size=3D"2">=C2=A0 s=
td::cerr &lt;&lt; x[0] &lt;&lt; &quot;\n&quot;;</font></div><div><font size=
=3D"2">=C2=A0 auto y =3D x;</font></div><div><font size=3D"2">}</font></div=
></div><div><font size=3D"2"><br></font></div><div><font size=3D"2">This ex=
ample runs and prints:</font></div><div><font size=3D"2"><br></font></div><=
div><div><font size=3D"2">copy</font></div><div><font size=3D"2">1</font></=
div><div><font size=3D"2">blah</font></div><div><font size=3D"2">copy</font=
></div></div><div><font size=3D"2"><br></font></div><div><font size=3D"2">S=
o constructing our container, which should simply default construct an allo=
cator, also makes a copy, despite there being no &quot;conceptual&quot; cop=
y. When we copy construct, we create a new allocator using select_on_contai=
ner_copy_<wbr>construction, and copy that new allocator, which is also unne=
cessary.</font></div><div><font size=3D"2"><br></font></div><div><font size=
=3D"2">If these unnecessary copies were eliminated, then it would actually =
be quite simple =C2=A0to write allocators that owned their own resources. S=
uch an allocator just needs a default constructor and move/swap, which is t=
ypically =C2=A0These have multiple applications:</font></div><div><ul><li><=
span style=3D"line-height:normal"><font size=3D"2">For data structures that=
 perform many small allocations (like map and set), such an allocator would=
 allow making some speed vs space trade-offs by chunking up allocations. Th=
is can be done in the current framework, but requires introducing a memory =
pool, which often has separate lifetime, or perhaps is co-owned by its allo=
cators via shared_ptr. Using an owning allocator is much simpler and hassle=
 free; it is a drop in replacement with a typedef.</font></span></li><li><s=
pan style=3D"line-height:normal"><font size=3D"2">It allows one to force th=
e small X optimization on any data structure (less efficiently, of course).=
 For instance, one could create an allocator that deliberately contains 64 =
bytes of empty storage. Allocation requests for 64 bytes or less are served=
 from this buffer, anything larger is sent to the heap. Convenient e.g. for=
 std::function, or std::vector, and easy to customize.</font></span></li><l=
i><span style=3D"line-height:normal"><font size=3D"2">It has interesting po=
ssibilities combined with scoped_allocators. I admit I haven&#39;t investig=
ated these in depth, but it seems like it would allow scenarios similar to =
the first example; e.g. consider a vector&lt;string&gt;. The inside strings=
 are likely to make many small allocation requests. If the vector has a sco=
ped allocator that owns it own resources (i.e. allocates large chunks of me=
mory), then it can give the strings allocators that reference the outer all=
ocator. Again, the same can be accomplished with memory pools, but this is =
cleaner.</font></span></li></ul><div><font size=3D"2">My proposal would bas=
ically be to change the Allocator concept so that copy constructability is =
only necessary if=C2=A0</font><span style=3D"color:rgb(0,0,0);font-family:D=
ejaVuSansMono,&#39;DejaVu Sans Mono&#39;,courier,monospace;font-size:small;=
white-space:nowrap;background-color:rgba(0,0,0,0.027451)">select_on_contain=
er_copy_<wbr>construction</span><span style=3D"font-size:small">=C2=A0is no=
t defined, or if the allocator uses it internally. In turn, AllocatorAware =
would be changed to never make unnecessary copies; which would also mean ch=
anging the standard library. This does not require any core language change=
s, and what&#39;s more it is backwards compatible. Since it broadens the de=
finition of legal allocators, all existing allocators would continue to be =
allocators and usable in the STL. It would mean that technically, user writ=
ten AllocatorAware containers would not be strictly compliant, but they wou=
ld keep working with std::allocator (which is copyable of course) and any a=
llocators they had written themselves.=C2=A0</span></div><div><font size=3D=
"2"><br></font></div></div><div><font size=3D"2">Thoughts and criticism wel=
come!</font></div></div></blockquote></div></blockquote></div>

<p></p>

-- <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 <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/33f9bac7-4b88-4620-b3c7-ed914f93299a%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/33f9bac7-4b88-4620-b3c7-ed914f93299a=
%40isocpp.org</a>.<br />

------=_Part_5523_1702318432.1459262574757--
------=_Part_5522_1515053557.1459262574756--

.


Author: quicknir@gmail.com
Date: Tue, 29 Mar 2016 07:59:48 -0700 (PDT)
Raw View
------=_Part_5550_2113064325.1459263588912
Content-Type: multipart/alternative;
 boundary="----=_Part_5551_1600389903.1459263588913"

------=_Part_5551_1600389903.1459263588913
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

Thanks for the good point about "never equal".

The fact that the small function optimization takes place outside the=20
allocator isn't what makes it impossible (as I later realized) to exploit=
=20
this technique for std::function. After all, the small string optimization=
=20
takes place outside the allocator for string, yet it would still be=20
possible to write an allocator that owns stack resources and get a "medium"=
=20
string optimization without touching string's source code in any way. The=
=20
problem is that std::function type erases its allocator. Since the=20
allocator is not part of the type, it already lives on the heap from the=20
get-go, so the allocator cannot help you put anything on the stack. I=20
understand why std::function is written this way; it makes sense in the=20
common use case even if it happens to make this optimization impossible.

> =E2=80=A6 and lest it be overlooked, if these allocators aren=E2=80=99t c=
opyable, they=E2=80=99re=20
not movable either.

Yes, that is a good point. It took me a while to parse Yun's post. I may=20
need to think a bit more about a stack-space owning allocator. For anything=
=20
that lives entirely on the stack and contains no pointers, copying and=20
moving are equivalent as you point out. So making it uncopyable is the same=
=20
as making it unmovable. The problem is I really don't like the idea of=20
unmovable objects; they're extremely rare, and hard to work with. The flip=
=20
side is though that the stack owning allocator cannot really copy/move=20
itself without copying/moving the elements. This may actually be ok as the=
=20
allocator is templated on the type it holds, so it can actually move the=20
objects around if it needs to. I'm not sure which alternative is=20
better/worse.

On Saturday, March 26, 2016 at 12:59:20 PM UTC-4, David Krauss wrote:
>
>
> On 2016=E2=80=9301=E2=80=9317, at 7:38 AM, quic...@gmail.com <javascript:=
> wrote:
>
> But what if your allocators want to own their own resources? Such=20
> allocators can never really allocate or deallocate each other's pointers,=
=20
> so they can never compare equal. This sounds like a big deal, but if your=
=20
> allocator is uncopyable, then it's not an issue; there's no real situatio=
n=20
> where you would ever necessarily expect them to compare equal.
>
>
> It would be nice to see this avenue pursued. It would allow =E2=80=9Csmal=
l=E2=80=9D or=20
> =E2=80=9Clocal=E2=80=9D vectors to be specializations of std::vector. Loc=
ally-optimized=20
> versions of all the standard containers would appear for minimal effort.
>
>
> On 2016=E2=80=9301=E2=80=9317, at 12:12 PM, Zhihao Yuan <z...@miator.net =
<javascript:>>=20
> wrote:
>
> There won't be any issue after
>
>  http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2015/p0135r0.html
>
> being accepted.
>
>
> The interface for initializing and retrieving the internal allocator woul=
d=20
> need to be revised, at least for the new local allocators. It would be ni=
ce=20
> to even remove it, but querying the remaining capacity is too useful.
>
> (Regarding =E2=80=9Cnever equal,=E2=80=9D pedantically, if you can obtain=
 a reference to a=20
> local allocator, then it should compare equal to itself.)
>
>
> On 2016=E2=80=9301=E2=80=9317, at 3:50 PM, quic...@gmail.com <javascript:=
> wrote:
>
>
> Not sure what polymorphic means in this context (polymorphic allocator?),
>
>
> Polymorphic allocators exist on the opposite end of the overall problem=
=20
> domain of allocators. Every allocator object gets reduced to a polymorphi=
c=20
> pointer, and every allocation and deallocation is dispatched as a virtual=
=20
> function. This helps interoperability at the expense of performance. It=
=E2=80=99s=20
> part of the Fundamentals TS; it may or may not be adopted by C++17.
>
> I've literally seen examples of people rewriting std::function from=20
> scratch so that they could change the size of the small function=20
> optimization because heap allocation is a major issue for them.
>
>
> This seems to be fairly common. Unfortunately, the small function=20
> optimization takes place outside the allocator. You could perhaps hack a=
=20
> local allocator into my function_container=20
> <https://github.com/potswa/cxx_function> template. But you=E2=80=99d want=
 to=20
> forbid converting that back to an ordinary function, or else do something=
=20
> clever like heap-allocate the local allocator. The library doesn=E2=80=99=
t provide=20
> for that. Also, the ordinary small-function optimization would be made=20
> redundant=E2=80=A6 it=E2=80=99s possible that this is an entirely differe=
nt problem.
>
>
> On 2016=E2=80=9303=E2=80=9326, at 11:44 PM, Yun Chen <yun.g...@gmail.com =
<javascript:>>=20
> wrote:
>
> We should extend it to move construction through=20
> select_on_container_move_construction, as we need the ability of default=
=20
> constructing the allocator too. This would be required to move construct =
an=20
> container in an arena from stack. =20
>
>
> =E2=80=A6 and lest it be overlooked, if these allocators aren=E2=80=99t c=
opyable, they=E2=80=99re=20
> not movable either.
>
>

--=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.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/76803d44-a7b2-4bf1-8e5c-268a2c88c48c%40isocpp.or=
g.

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

<div dir=3D"ltr">Thanks for the good point about &quot;never equal&quot;.<d=
iv><br></div><div>The fact that the small function optimization takes place=
 outside the allocator isn&#39;t what makes it impossible (as I later reali=
zed) to exploit this technique for std::function. After all, the small stri=
ng optimization takes place outside the allocator for string, yet it would =
still be possible to write an allocator that owns stack resources and get a=
 &quot;medium&quot; string optimization without touching string&#39;s sourc=
e code in any way. The problem is that std::function type erases its alloca=
tor. Since the allocator is not part of the type, it already lives on the h=
eap from the get-go, so the allocator cannot help you put anything on the s=
tack. I understand why std::function is written this way; it makes sense in=
 the common use case even if it happens to make this optimization impossibl=
e.</div><div><br></div><div>&gt; =E2=80=A6 and lest it be overlooked, if th=
ese allocators aren=E2=80=99t copyable, they=E2=80=99re not movable either.=
</div><div><br></div><div>Yes, that is a good point. It took me a while to =
parse Yun&#39;s post. I may need to think a bit more about a stack-space ow=
ning allocator. For anything that lives entirely on the stack and contains =
no pointers, copying and moving are equivalent as you point out. So making =
it uncopyable is the same as making it unmovable. The problem is I really d=
on&#39;t like the idea of unmovable objects; they&#39;re extremely rare, an=
d hard to work with. The flip side is though that the stack owning allocato=
r cannot really copy/move itself without copying/moving the elements. This =
may actually be ok as the allocator is templated on the type it holds, so i=
t can actually move the objects around if it needs to. I&#39;m not sure whi=
ch alternative is better/worse.<br><br>On Saturday, March 26, 2016 at 12:59=
:20 PM UTC-4, David Krauss wrote:<blockquote class=3D"gmail_quote" style=3D=
"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex=
;"><div style=3D"word-wrap:break-word"><div><br></div><blockquote type=3D"c=
ite"><div>On 2016=E2=80=9301=E2=80=9317, at 7:38 AM, <a href=3D"javascript:=
" target=3D"_blank" gdf-obfuscated-mailto=3D"JHA8hnTYCwAJ" rel=3D"nofollow"=
 onmousedown=3D"this.href=3D&#39;javascript:&#39;;return true;" onclick=3D"=
this.href=3D&#39;javascript:&#39;;return true;">quic...@gmail.com</a> wrote=
:</div><br><div><span style=3D"float:none;display:inline!important">But wha=
t if your allocators want to own their own resources? Such allocators can n=
ever really allocate or deallocate each other&#39;s pointers, so they can n=
ever compare equal. This sounds like a big deal, but if your allocator is u=
ncopyable, then it&#39;s not an issue; there&#39;s no real situation where =
you would ever necessarily expect them to compare equal.</span></div></bloc=
kquote><div><div><span style=3D"float:none;display:inline!important"><br></=
span></div></div><div><span style=3D"float:none;display:inline!important">I=
t would be nice to see this avenue pursued. It would allow =E2=80=9Csmall=
=E2=80=9D or =E2=80=9Clocal=E2=80=9D vectors to be specializations of <font=
 face=3D"Courier">std::vector</font>. Locally-optimized versions of all the=
 standard containers would appear for minimal effort.</span></div><div><br>=
</div><div><span style=3D"font-size:small;float:none;display:inline!importa=
nt"><br></span></div><div><blockquote type=3D"cite"><div>On 2016=E2=80=9301=
=E2=80=9317, at 12:12 PM, Zhihao Yuan &lt;<a href=3D"javascript:" target=3D=
"_blank" gdf-obfuscated-mailto=3D"JHA8hnTYCwAJ" rel=3D"nofollow" onmousedow=
n=3D"this.href=3D&#39;javascript:&#39;;return true;" onclick=3D"this.href=
=3D&#39;javascript:&#39;;return true;">z...@miator.net</a>&gt; wrote:</div>=
<br><div><div>There won&#39;t be any issue after<br><br> =C2=A0<a href=3D"h=
ttp://www.open-std.org/JTC1/SC22/WG21/docs/papers/2015/p0135r0.html" target=
=3D"_blank" rel=3D"nofollow" onmousedown=3D"this.href=3D&#39;http://www.goo=
gle.com/url?q\75http%3A%2F%2Fwww.open-std.org%2FJTC1%2FSC22%2FWG21%2Fdocs%2=
Fpapers%2F2015%2Fp0135r0.html\46sa\75D\46sntz\0751\46usg\75AFQjCNEvCUGb8Snt=
GH2yWDyjeRZtZwNngA&#39;;return true;" onclick=3D"this.href=3D&#39;http://ww=
w.google.com/url?q\75http%3A%2F%2Fwww.open-std.org%2FJTC1%2FSC22%2FWG21%2Fd=
ocs%2Fpapers%2F2015%2Fp0135r0.html\46sa\75D\46sntz\0751\46usg\75AFQjCNEvCUG=
b8SntGH2yWDyjeRZtZwNngA&#39;;return true;">http://www.open-std.org/JTC1/<wb=
r>SC22/WG21/docs/papers/2015/<wbr>p0135r0.html</a><br><br>being accepted.<b=
r></div></div></blockquote></div><br><div>The interface for initializing an=
d retrieving the internal allocator would need to be revised, at least for =
the new local allocators. It would be nice to even remove it, but querying =
the remaining capacity is too useful.</div><div><br></div><div>(Regarding =
=E2=80=9Cnever equal,=E2=80=9D pedantically, if you can obtain a reference =
to a local allocator, then it should compare equal to itself.)</div><div><b=
r></div><div><br></div><div><blockquote type=3D"cite">On 2016=E2=80=9301=E2=
=80=9317, at 3:50 PM, <a href=3D"javascript:" target=3D"_blank" gdf-obfusca=
ted-mailto=3D"JHA8hnTYCwAJ" rel=3D"nofollow" onmousedown=3D"this.href=3D&#3=
9;javascript:&#39;;return true;" onclick=3D"this.href=3D&#39;javascript:&#3=
9;;return true;">quic...@gmail.com</a> wrote:</blockquote><blockquote type=
=3D"cite"><br><div></div></blockquote><blockquote type=3D"cite"><div><span =
style=3D"float:none;display:inline!important">Not sure what polymorphic mea=
ns in this context (polymorphic allocator?),</span></div></blockquote><div>=
<br></div><div>Polymorphic allocators exist on the opposite end of the over=
all problem domain of allocators. Every allocator object gets reduced to a =
polymorphic pointer, and every allocation and deallocation is dispatched as=
 a virtual function. This helps interoperability at the expense of performa=
nce. It=E2=80=99s part of the Fundamentals TS; it may or may not be adopted=
 by C++17.</div><br><blockquote type=3D"cite"><div><span style=3D"float:non=
e;display:inline!important"> I&#39;ve literally seen examples of people rew=
riting std::function from scratch so that they could change the size of the=
 small function optimization because heap allocation is a major issue for t=
hem.</span></div></blockquote><br></div><div>This seems to be fairly common=
.. Unfortunately, the small function optimization takes place outside the al=
locator. You could perhaps hack a local allocator into my=C2=A0<a href=3D"h=
ttps://github.com/potswa/cxx_function" target=3D"_blank" rel=3D"nofollow" o=
nmousedown=3D"this.href=3D&#39;https://www.google.com/url?q\75https%3A%2F%2=
Fgithub.com%2Fpotswa%2Fcxx_function\46sa\75D\46sntz\0751\46usg\75AFQjCNFguf=
h0L0h21l02YtBJVM-00lMVug&#39;;return true;" onclick=3D"this.href=3D&#39;htt=
ps://www.google.com/url?q\75https%3A%2F%2Fgithub.com%2Fpotswa%2Fcxx_functio=
n\46sa\75D\46sntz\0751\46usg\75AFQjCNFgufh0L0h21l02YtBJVM-00lMVug&#39;;retu=
rn true;"><font face=3D"Courier">function_container</font></a>=C2=A0<wbr>te=
mplate. But you=E2=80=99d want to forbid converting that back to an ordinar=
y <font face=3D"Courier">function</font>, or else do something clever like =
heap-allocate the local allocator. The library doesn=E2=80=99t provide for =
that. Also, the ordinary small-function optimization would be made redundan=
t=E2=80=A6 it=E2=80=99s possible that this is an entirely different problem=
..</div><div><br></div><div><br></div><div><blockquote type=3D"cite"><div>On=
 2016=E2=80=9303=E2=80=9326, at 11:44 PM, Yun Chen &lt;<a href=3D"javascrip=
t:" target=3D"_blank" gdf-obfuscated-mailto=3D"JHA8hnTYCwAJ" rel=3D"nofollo=
w" onmousedown=3D"this.href=3D&#39;javascript:&#39;;return true;" onclick=
=3D"this.href=3D&#39;javascript:&#39;;return true;">yun.g...@gmail.com</a>&=
gt; wrote:</div><br><div><div>We should extend it to move construction thro=
ugh select_on_container_move_<wbr>construction, as we need the ability of d=
efault constructing the allocator too. This would be required to move const=
ruct an container in an arena from stack. =C2=A0</div></div></blockquote><b=
r></div><div>=E2=80=A6 and lest it be overlooked, if these allocators aren=
=E2=80=99t copyable, they=E2=80=99re not movable either.</div><div><br></di=
v></div></blockquote></div></div>

<p></p>

-- <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 <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/76803d44-a7b2-4bf1-8e5c-268a2c88c48c%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/76803d44-a7b2-4bf1-8e5c-268a2c88c48c=
%40isocpp.org</a>.<br />

------=_Part_5551_1600389903.1459263588913--
------=_Part_5550_2113064325.1459263588912--

.


Author: David Krauss <potswa@gmail.com>
Date: Wed, 30 Mar 2016 10:54:59 +0800
Raw View
--Apple-Mail=_1DB1EEEB-A5B1-426D-A27F-9B63D730B9D1
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8


> On 2016=E2=80=9303=E2=80=9329, at 10:59 PM, quicknir@gmail.com wrote:
>=20
> Thanks for the good point about "never equal".
>=20
> The fact that the small function optimization takes place outside the all=
ocator isn't what makes it impossible (as I later realized) to exploit this=
 technique for std::function. After all, the small string optimization take=
s place outside the allocator for string, yet it would still be possible to=
 write an allocator that owns stack resources and get a "medium" string opt=
imization without touching string's source code in any way. The problem is =
that std::function type erases its allocator. Since the allocator is not pa=
rt of the type, it already lives on the heap from the get-go, so the alloca=
tor cannot help you put anything on the stack. I understand why std::functi=
on is written this way; it makes sense in the common use case even if it ha=
ppens to make this optimization impossible.

That=E2=80=99s right for std::function, but you still might take a look at =
the function_container class in my library <https://github.com/potswa/cxx_f=
unction>  I=E2=80=99ve written one proposal for it already (P0043), and I=
=E2=80=99d like for such a thing to be either standard or user-implementabl=
e with interoperability with std::function. (The distinction between =E2=80=
=9Csmall=E2=80=9D and =E2=80=9Cmedium=E2=80=9D represents unnecessary overh=
ead, though.)

> > =E2=80=A6 and lest it be overlooked, if these allocators aren=E2=80=99t=
 copyable, they=E2=80=99re not movable either.
>=20
> Yes, that is a good point. It took me a while to parse Yun's post. I may =
need to think a bit more about a stack-space owning allocator. For anything=
 that lives entirely on the stack and contains no pointers, copying and mov=
ing are equivalent as you point out. So making it uncopyable is the same as=
 making it unmovable. The problem is I really don't like the idea of unmova=
ble objects; they're extremely rare, and hard to work with. The flip side i=
s though that the stack owning allocator cannot really copy/move itself wit=
hout copying/moving the elements. This may actually be ok as the allocator =
is templated on the type it holds, so it can actually move the objects arou=
nd if it needs to. I'm not sure which alternative is better/worse.

The semantics are what they are what they are, like it or not: the allocato=
r isn=E2=80=99t practically able to make another of itself.


An allocator should certainly not be aware of the contents of its allocatio=
n blocks. For one thing, it can=E2=80=99t assume that they contain construc=
ted objects. (This may be sort-of implementable if construct and destroy pe=
rform bookkeeping, but not without overhead. And the user is free to reuse =
the storage for other things.)

Which is easier:
1. An allocator which lives inside a movable and copyable container, but wh=
ich is ill-formed if you attempt a move operation on the allocator itself.
2. An allocator which allows copy (and move-as-copy) operations, with surpr=
ising and not-allocator-like semantics.

=E2=80=9CHard to work with=E2=80=9D is a good thing for objects with tricky=
 semantics.

--=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.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/B7F34041-242E-434C-B2F1-114B67A7C6F2%40gmail.com=
..

--Apple-Mail=_1DB1EEEB-A5B1-426D-A27F-9B63D730B9D1
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8

<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dutf-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: s=
pace; -webkit-line-break: after-white-space;" class=3D""><br class=3D""><di=
v><blockquote type=3D"cite" class=3D""><div class=3D"">On 2016=E2=80=9303=
=E2=80=9329, at 10:59 PM, <a href=3D"mailto:quicknir@gmail.com" class=3D"">=
quicknir@gmail.com</a> wrote:</div><br class=3D"Apple-interchange-newline">=
<div class=3D""><div dir=3D"ltr" class=3D"">Thanks for the good point about=
 "never equal".<div class=3D""><br class=3D""></div><div class=3D"">The fac=
t that the small function optimization takes place outside the allocator is=
n't what makes it impossible (as I later realized) to exploit this techniqu=
e for std::function. After all, the small string optimization takes place o=
utside the allocator for string, yet it would still be possible to write an=
 allocator that owns stack resources and get a "medium" string optimization=
 without touching string's source code in any way. The problem is that std:=
:function type erases its allocator. Since the allocator is not part of the=
 type, it already lives on the heap from the get-go, so the allocator canno=
t help you put anything on the stack. I understand why std::function is wri=
tten this way; it makes sense in the common use case even if it happens to =
make this optimization impossible.</div><div class=3D""></div></div></div><=
/blockquote><div><br class=3D""></div><div>That=E2=80=99s right for <font f=
ace=3D"Courier" class=3D"">std::function</font>, but you still might take a=
 look at the <font face=3D"Courier" class=3D"">function_container</font> cl=
ass in my&nbsp;<a href=3D"https://github.com/potswa/cxx_function" class=3D"=
">library</a>&nbsp; I=E2=80=99ve written one proposal for it already (P0043=
), and I=E2=80=99d like for such a thing to be either standard or user-impl=
ementable with interoperability with <font face=3D"Courier" class=3D"">std:=
:function</font>. (The distinction between =E2=80=9Csmall=E2=80=9D and =E2=
=80=9Cmedium=E2=80=9D represents unnecessary overhead, though.)</div><br cl=
ass=3D""><blockquote type=3D"cite" class=3D""><div class=3D""><div dir=3D"l=
tr" class=3D""><div class=3D"">&gt; =E2=80=A6 and lest it be overlooked, if=
 these allocators aren=E2=80=99t copyable, they=E2=80=99re not movable eith=
er.</div><div class=3D""><br class=3D""></div><div class=3D"">Yes, that is =
a good point. It took me a while to parse Yun's post. I may need to think a=
 bit more about a stack-space owning allocator. For anything that lives ent=
irely on the stack and contains no pointers, copying and moving are equival=
ent as you point out. So making it uncopyable is the same as making it unmo=
vable. The problem is I really don't like the idea of unmovable objects; th=
ey're extremely rare, and hard to work with. The flip side is though that t=
he stack owning allocator cannot really copy/move itself without copying/mo=
ving the elements. This may actually be ok as the allocator is templated on=
 the type it holds, so it can actually move the objects around if it needs =
to. I'm not sure which alternative is better/worse.</div></div></div></bloc=
kquote></div><br class=3D""><div class=3D"">The semantics are what they are=
 what they are, like it or not: the allocator isn=E2=80=99t practically abl=
e to make another of itself.</div><div class=3D""><br class=3D""><blockquot=
e type=3D"cite" class=3D""><div dir=3D"ltr" class=3D""></div></blockquote><=
/div><div class=3D"">An allocator should certainly not be aware of the cont=
ents of its allocation blocks. For one thing, it can=E2=80=99t assume that =
they contain constructed objects. (This may be sort-of implementable if <fo=
nt face=3D"Courier" class=3D"">construct</font> and <font face=3D"Courier" =
class=3D"">destroy</font> perform bookkeeping, but not without overhead. An=
d the user is free to reuse the storage for other things.)</div><div class=
=3D""><br class=3D""></div><div class=3D"">Which is easier:</div><div class=
=3D"">1. An allocator which lives inside a movable and copyable container, =
but which is ill-formed if you attempt a move operation on the allocator it=
self.</div><div class=3D"">2. An allocator which allows copy (and move-as-c=
opy) operations, with surprising and not-allocator-like semantics.</div><di=
v class=3D""><br class=3D""></div><div class=3D"">=E2=80=9CHard to work wit=
h=E2=80=9D is a good thing for objects with tricky semantics.</div><div cla=
ss=3D""><br class=3D""></div></body></html>

<p></p>

-- <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 <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/B7F34041-242E-434C-B2F1-114B67A7C6F2%=
40gmail.com?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/B7F34041-242E-434C-B2F1-114B67A7C6F2%=
40gmail.com</a>.<br />

--Apple-Mail=_1DB1EEEB-A5B1-426D-A27F-9B63D730B9D1--

.


Author: Sean Middleditch <sean.middleditch@gmail.com>
Date: Wed, 30 Mar 2016 18:07:57 -0700 (PDT)
Raw View
------=_Part_8693_980243304.1459386478134
Content-Type: multipart/alternative;
 boundary="----=_Part_8694_621060238.1459386478134"

------=_Part_8694_621060238.1459386478134
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

On Saturday, March 26, 2016 at 9:59:20 AM UTC-7, David Krauss wrote:
>
>
> On 2016=E2=80=9301=E2=80=9317, at 7:38 AM, quic...@gmail.com <javascript:=
> wrote:
>
> But what if your allocators want to own their own resources? Such=20
> allocators can never really allocate or deallocate each other's pointers,=
=20
> so they can never compare equal. This sounds like a big deal, but if your=
=20
> allocator is uncopyable, then it's not an issue; there's no real situatio=
n=20
> where you would ever necessarily expect them to compare equal.
>
>
> It would be nice to see this avenue pursued. It would allow =E2=80=9Csmal=
l=E2=80=9D or=20
> =E2=80=9Clocal=E2=80=9D vectors to be specializations of std::vector. Loc=
ally-optimized=20
> versions of all the standard containers would appear for minimal effort.
>

Not by itself. There's still that small problem where the allocator has no=
=20
idea what growth pattern the vector uses while the vector has no idea what=
=20
the best initial size classes for the allocator would be. There's an extra=
=20
missing bit of "protocol" needed between the two in order to fully=20
genericize "small" or "fixed" containers like vector. Otherwise you end up=
=20
with allocators that have room for up to 7 elements while the container=20
tries to allocate room for an initial capacity of 16 elements.

The naive approach would work for just the small/fixed container use case.=
=20
A good approach would likely work for other cases, e.g. a page allocator=20
backing a vector requiring that the vector grow only in=20
multiple-of-page-size increments.
=20

>
>
> On 2016=E2=80=9301=E2=80=9317, at 12:12 PM, Zhihao Yuan <z...@miator.net =
<javascript:>>=20
> wrote:
>
> There won't be any issue after
>
>  http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2015/p0135r0.html
>
> being accepted.
>
>
> The interface for initializing and retrieving the internal allocator woul=
d=20
> need to be revised, at least for the new local allocators. It would be ni=
ce=20
> to even remove it, but querying the remaining capacity is too useful.
>
> (Regarding =E2=80=9Cnever equal,=E2=80=9D pedantically, if you can obtain=
 a reference to a=20
> local allocator, then it should compare equal to itself.)
>
>
> On 2016=E2=80=9301=E2=80=9317, at 3:50 PM, quic...@gmail.com <javascript:=
> wrote:
>
>
> Not sure what polymorphic means in this context (polymorphic allocator?),
>
>
> Polymorphic allocators exist on the opposite end of the overall problem=
=20
> domain of allocators. Every allocator object gets reduced to a polymorphi=
c=20
> pointer, and every allocation and deallocation is dispatched as a virtual=
=20
> function. This helps interoperability at the expense of performance. It=
=E2=80=99s=20
> part of the Fundamentals TS; it may or may not be adopted by C++17.
>
> I've literally seen examples of people rewriting std::function from=20
> scratch so that they could change the size of the small function=20
> optimization because heap allocation is a major issue for them.
>
>
> This seems to be fairly common. Unfortunately, the small function=20
> optimization takes place outside the allocator. You could perhaps hack a=
=20
> local allocator into my function_container=20
> <https://github.com/potswa/cxx_function> template. But you=E2=80=99d want=
 to=20
> forbid converting that back to an ordinary function, or else do something=
=20
> clever like heap-allocate the local allocator. The library doesn=E2=80=99=
t provide=20
> for that. Also, the ordinary small-function optimization would be made=20
> redundant=E2=80=A6 it=E2=80=99s possible that this is an entirely differe=
nt problem.
>
>
> On 2016=E2=80=9303=E2=80=9326, at 11:44 PM, Yun Chen <yun.g...@gmail.com =
<javascript:>>=20
> wrote:
>
> We should extend it to move construction through=20
> select_on_container_move_construction, as we need the ability of default=
=20
> constructing the allocator too. This would be required to move construct =
an=20
> container in an arena from stack. =20
>
>
> =E2=80=A6 and lest it be overlooked, if these allocators aren=E2=80=99t c=
opyable, they=E2=80=99re=20
> not movable either.
>
>

--=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.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/137dc707-14b3-417f-9a06-362c466ef47d%40isocpp.or=
g.

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

<div dir=3D"ltr">On Saturday, March 26, 2016 at 9:59:20 AM UTC-7, David Kra=
uss wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left:=
 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div style=3D"word-w=
rap:break-word"><div><br></div><blockquote type=3D"cite"><div>On 2016=E2=80=
=9301=E2=80=9317, at 7:38 AM, <a href=3D"javascript:" target=3D"_blank" gdf=
-obfuscated-mailto=3D"JHA8hnTYCwAJ" rel=3D"nofollow" onmousedown=3D"this.hr=
ef=3D&#39;javascript:&#39;;return true;" onclick=3D"this.href=3D&#39;javasc=
ript:&#39;;return true;">quic...@gmail.com</a> wrote:</div><br><div><span s=
tyle=3D"float:none;display:inline!important">But what if your allocators wa=
nt to own their own resources? Such allocators can never really allocate or=
 deallocate each other&#39;s pointers, so they can never compare equal. Thi=
s sounds like a big deal, but if your allocator is uncopyable, then it&#39;=
s not an issue; there&#39;s no real situation where you would ever necessar=
ily expect them to compare equal.</span></div></blockquote><div><div><span =
style=3D"float:none;display:inline!important"><br></span></div></div><div><=
span style=3D"float:none;display:inline!important">It would be nice to see =
this avenue pursued. It would allow =E2=80=9Csmall=E2=80=9D or =E2=80=9Cloc=
al=E2=80=9D vectors to be specializations of <font face=3D"Courier">std::ve=
ctor</font>. Locally-optimized versions of all the standard containers woul=
d appear for minimal effort.</span></div></div></blockquote><div><br></div>=
<div>Not by itself. There&#39;s still that small problem where the allocato=
r has no idea what growth pattern the vector uses while the vector has no i=
dea what the best initial size classes for the allocator would be. There&#3=
9;s an extra missing bit of &quot;protocol&quot; needed between the two in =
order to fully genericize &quot;small&quot; or &quot;fixed&quot; containers=
 like vector. Otherwise you end up with allocators that have room for up to=
 7 elements while the container tries to allocate room for an initial capac=
ity of 16 elements.</div><div><br></div><div>The naive approach would work =
for just the small/fixed container use case. A good approach would likely w=
ork for other cases, e.g. a page allocator backing a vector requiring that =
the vector grow only in multiple-of-page-size increments.</div><div>=C2=A0<=
/div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8e=
x;border-left: 1px #ccc solid;padding-left: 1ex;"><div style=3D"word-wrap:b=
reak-word"><div><br></div><div><span style=3D"font-size:small;float:none;di=
splay:inline!important"><br></span></div><div><blockquote type=3D"cite"><di=
v>On 2016=E2=80=9301=E2=80=9317, at 12:12 PM, Zhihao Yuan &lt;<a href=3D"ja=
vascript:" target=3D"_blank" gdf-obfuscated-mailto=3D"JHA8hnTYCwAJ" rel=3D"=
nofollow" onmousedown=3D"this.href=3D&#39;javascript:&#39;;return true;" on=
click=3D"this.href=3D&#39;javascript:&#39;;return true;">z...@miator.net</a=
>&gt; wrote:</div><br><div><div>There won&#39;t be any issue after<br><br> =
=C2=A0<a href=3D"http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2015/p0=
135r0.html" target=3D"_blank" rel=3D"nofollow" onmousedown=3D"this.href=3D&=
#39;http://www.google.com/url?q\75http%3A%2F%2Fwww.open-std.org%2FJTC1%2FSC=
22%2FWG21%2Fdocs%2Fpapers%2F2015%2Fp0135r0.html\46sa\75D\46sntz\0751\46usg\=
75AFQjCNEvCUGb8SntGH2yWDyjeRZtZwNngA&#39;;return true;" onclick=3D"this.hre=
f=3D&#39;http://www.google.com/url?q\75http%3A%2F%2Fwww.open-std.org%2FJTC1=
%2FSC22%2FWG21%2Fdocs%2Fpapers%2F2015%2Fp0135r0.html\46sa\75D\46sntz\0751\4=
6usg\75AFQjCNEvCUGb8SntGH2yWDyjeRZtZwNngA&#39;;return true;">http://www.ope=
n-std.org/JTC1/<wbr>SC22/WG21/docs/papers/2015/<wbr>p0135r0.html</a><br><br=
>being accepted.<br></div></div></blockquote></div><br><div>The interface f=
or initializing and retrieving the internal allocator would need to be revi=
sed, at least for the new local allocators. It would be nice to even remove=
 it, but querying the remaining capacity is too useful.</div><div><br></div=
><div>(Regarding =E2=80=9Cnever equal,=E2=80=9D pedantically, if you can ob=
tain a reference to a local allocator, then it should compare equal to itse=
lf.)</div><div><br></div><div><br></div><div><blockquote type=3D"cite">On 2=
016=E2=80=9301=E2=80=9317, at 3:50 PM, <a href=3D"javascript:" target=3D"_b=
lank" gdf-obfuscated-mailto=3D"JHA8hnTYCwAJ" rel=3D"nofollow" onmousedown=
=3D"this.href=3D&#39;javascript:&#39;;return true;" onclick=3D"this.href=3D=
&#39;javascript:&#39;;return true;">quic...@gmail.com</a> wrote:</blockquot=
e><blockquote type=3D"cite"><br><div></div></blockquote><blockquote type=3D=
"cite"><div><span style=3D"float:none;display:inline!important">Not sure wh=
at polymorphic means in this context (polymorphic allocator?),</span></div>=
</blockquote><div><br></div><div>Polymorphic allocators exist on the opposi=
te end of the overall problem domain of allocators. Every allocator object =
gets reduced to a polymorphic pointer, and every allocation and deallocatio=
n is dispatched as a virtual function. This helps interoperability at the e=
xpense of performance. It=E2=80=99s part of the Fundamentals TS; it may or =
may not be adopted by C++17.</div><br><blockquote type=3D"cite"><div><span =
style=3D"float:none;display:inline!important"> I&#39;ve literally seen exam=
ples of people rewriting std::function from scratch so that they could chan=
ge the size of the small function optimization because heap allocation is a=
 major issue for them.</span></div></blockquote><br></div><div>This seems t=
o be fairly common. Unfortunately, the small function optimization takes pl=
ace outside the allocator. You could perhaps hack a local allocator into my=
=C2=A0<a href=3D"https://github.com/potswa/cxx_function" target=3D"_blank" =
rel=3D"nofollow" onmousedown=3D"this.href=3D&#39;https://www.google.com/url=
?q\75https%3A%2F%2Fgithub.com%2Fpotswa%2Fcxx_function\46sa\75D\46sntz\0751\=
46usg\75AFQjCNFgufh0L0h21l02YtBJVM-00lMVug&#39;;return true;" onclick=3D"th=
is.href=3D&#39;https://www.google.com/url?q\75https%3A%2F%2Fgithub.com%2Fpo=
tswa%2Fcxx_function\46sa\75D\46sntz\0751\46usg\75AFQjCNFgufh0L0h21l02YtBJVM=
-00lMVug&#39;;return true;"><font face=3D"Courier">function_container</font=
></a>=C2=A0<wbr>template. But you=E2=80=99d want to forbid converting that =
back to an ordinary <font face=3D"Courier">function</font>, or else do some=
thing clever like heap-allocate the local allocator. The library doesn=E2=
=80=99t provide for that. Also, the ordinary small-function optimization wo=
uld be made redundant=E2=80=A6 it=E2=80=99s possible that this is an entire=
ly different problem.</div><div><br></div><div><br></div><div><blockquote t=
ype=3D"cite"><div>On 2016=E2=80=9303=E2=80=9326, at 11:44 PM, Yun Chen &lt;=
<a href=3D"javascript:" target=3D"_blank" gdf-obfuscated-mailto=3D"JHA8hnTY=
CwAJ" rel=3D"nofollow" onmousedown=3D"this.href=3D&#39;javascript:&#39;;ret=
urn true;" onclick=3D"this.href=3D&#39;javascript:&#39;;return true;">yun.g=
....@gmail.com</a>&gt; wrote:</div><br><div><div>We should extend it to move=
 construction through select_on_container_move_<wbr>construction, as we nee=
d the ability of default constructing the allocator too. This would be requ=
ired to move construct an container in an arena from stack. =C2=A0</div></d=
iv></blockquote><br></div><div>=E2=80=A6 and lest it be overlooked, if thes=
e allocators aren=E2=80=99t copyable, they=E2=80=99re not movable either.</=
div><div><br></div></div></blockquote></div>

<p></p>

-- <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 <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/137dc707-14b3-417f-9a06-362c466ef47d%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/137dc707-14b3-417f-9a06-362c466ef47d=
%40isocpp.org</a>.<br />

------=_Part_8694_621060238.1459386478134--
------=_Part_8693_980243304.1459386478134--

.