Open ericniebler opened 8 years ago
Everything in any_view
would also benefit greatly from small object optimizations to avoid tiny dynamic allocations for individual iterators and sentinels.
After #679:
any_view<T, input>
uses a distinct implementation strategy from the higher categories. Since only one copy of a single-pass View
can ever have begin
called on it, and only one copy of a single-pass Iterator
can be incremented, we can get away with storing a single iterator and sentinel alongside the adapted view in a single representation that is shared by all copies of that any_view
. Sentinels for the erased range are default_sentinel
, and its iterators are simply pointers to the shared representation. The net effect is that copying an any_view<T, input>
or its iterators or sentinels never results in allocation.
any_view<T, /* not input */>
is also slightly more allocation-efficient. any_sentinel
s are simply pointers: the adapted view's sentinel is stored alongside the view so that any_sentinel
has no allocated state.
This leaves two cases that could take advantage of small object optimizations: any_view<T, /* not input */>
and its iterators, or more precisely any_cursor
s.
See discussion in #449. Copying the iterators of an Input any_view does not need to clone the underlying cursor; copies can share a cursor.