v
vector<int> vec={3,2,1,3};min_element(vec.begin(),vec.end()) v{ 3 , 2 , 1 , 3 }
|
vector<int> vec={0,0,1,1};upper_bound(vec.begin(),vec.end(),0) | v{ 0 , 0 , 1 , 1 }
std::vector<int> v={0,0,1,1};auto it=find( v, 0); // first element of value 0.
vector<pair<int,char>> vec={{0,'a'},{0,'b'},{1,'a'},{1,'b'}};auto it=find_if( v, [](A const& a){ return a.first==0; } ); // first element of value 0 in first
vector<pair<int,char>> vec={{0,'a'},{0,'b'},{1,'a'},{1,'b'}};auto it=find_if( v, [](A const& a){ return a.first==0; } ); // first element of value 0 in first
auto trans=transform(vec, mem_fn(&pair<int,char>::first)); // {0,0,1,1}auto it=find(trans,0); // first element of value 0 in first
vec
not modifiedtrans
referencing vec
vector<pair<int,char>> vec={{0,'a'},{0,'b'},{1,'a'},{1,'b'}};find_if( v, [](A const& a){ return a.first==0; } )->second; // 'a' !
auto trans=transform(vec, mem_fn(&pair<int,char>::first)); // {0,0,1,1}find(trans,0)->second // 'a' ?
int
transform
to get iterator pointing to pair<int,char>
find(trans,0).base()->second // 'a'! v{ 0, 0, 1, 1 } // trans v // .base(){{0,'a'},{0,'b'},{1,'a'},{1,'b'}} // vec
find
returns iterator in role of element.base()
must preserve identity of elementfind(trans,0).base()->second // 'a' v{ 0, 0, 1, 1 } // trans v // .base(){{0,'a'},{0,'b'},{1,'a'},{1,'b'}} // vec
upper_bound
returns iterator in role of borderbase()
preserves identity of borderupper_bound(trans,0).base() | v{ 0, 0, 1, 1 } // trans | v // .base(){{0,'a'},{0,'b'},{1,'a'},{1,'b'}} // vec
vector<pair<int,char>> vec={{0,'a'},{0,'b'},{1,'a'},{1,'b'}};auto filt=filter(vec, [](auto const& p){return p.second=='b';}); // {{0,'b'},{1,'b'}}
auto trans=transform(filt, mem_fn(&pair<int,char>::first)); // {0,1}find(trans,0).base().base() v{ 0 , 1 } // trans v // .base(){ {0,'b'}, {1,'b'}} // filt v // .base(){{0,'a'},{0,'b'},{1,'a'},{1,'b'}} // vec
find
returns iterator in role of elementfilter
vector<pair<int,char>> vec={{0,'a'},{0,'b'},{1,'a'},{1,'b'}};auto filt=filter(vec, [](auto const& p){return p.second=='b';}); // {{0,'b'},{1,'b'}}
auto trans=transform(filt, mem_fn(&pair<int,char>::first)); // {0,1}find(trans,0).base().base() v{ 0 , 1 } // trans v // .base(){ {0,'b'}, {1,'b'}} // filt v // .base(){{0,'a'},{0,'b'},{1,'a'},{1,'b'}} // vec
find
returns iterator in role of elementfilter
.base()
preserves identity of elementvector<pair<int,char>> vec={{0,'a'},{0,'b'},{1,'a'},{1,'b'}};auto filt=filter(vec, [](auto const& p){return p.second=='b';}); // {{0,'b'},{1,'b'}}
auto trans=transform(filt, mem_fn(&pair<int,char>::first)); // {0,1}upper_bound(trans,0).base().base() | v{ 0 , 1 } // trans | v // .base(){ {0,'b'}, {1,'b'}} // filt | v // .base(){{0,'a'},{0,'b'},{1,'a'},{1,'b'}} // vec
.base()
preserves identity of elementvector<pair<int,char>> vec={{0,'a'},{0,'b'},{1,'a'},{1,'b'}};auto filt=filter(vec, [](auto const& p){return p.second=='b';}); // {{0,'b'},{1,'b'}}
auto trans=transform(filt, mem_fn(&pair<int,char>::first)); // {0,1}upper_bound(trans,0).base().base() | v{ 0 , 1 } // trans | v // .base(){ {0,'b'}, {1,'b'}} // filt |???????| v // .base(){{0,'a'},{0,'b'},{1,'a'},{1,'b'}} // vec
.base()
preserves identity of elementfilter(...).base()
ambiguous if iterator in role of bordervector<pair<int,char>> vec={{0,'a'},{0,'b'},{1,'a'},{1,'b'}};auto filt=filter(vec, [](auto const& p){return p.second=='b';}); // {{0,'b'},{1,'b'}}
auto trans=transform(filt, mem_fn(&pair<int,char>::first)); // {0,1}upper_bound(trans,0).base().base() | v{ 0 , 1 } // trans | v // .base(){ {0,'b'}, {1,'b'}} // filt |???????| v // .base(){{0,'a'},{0,'b'},{1,'a'},{1,'b'}} // vec
.base()
preserves identity of elementfilter(...).base()
ambiguous if iterator in role of bordervector<pair<int,char>> vec={{0,'a'},{0,'b'},{1,'a'},{1,'b'}};auto rev=reverse(vec); // {{1,'b'},{1,'a'},{0,'b'},{0,'a'}}
auto trans=transform(rev, mem_fn(&pair<int,char>::first)); // {1,1,0,0}find(trans,0).base().base() v{ 1 , 1 , 0 , 0 } // trans v // .base(){{1,'b'},{1,'a'},{0,'b'},{0,'a'}} // rev v // .base() {{0,'a'},{0,'b'},{1,'a'},{1,'b'}}; // vec
.base()
must preserve identity of elementvector<pair<int,char>> vec={{0,'a'},{0,'b'},{1,'a'},{1,'b'}};auto rev=reverse(vec); // {{1,'b'},{1,'a'},{0,'b'},{0,'a'}}
auto trans=transform(rev, mem_fn(&pair<int,char>::first)); // {1,1,0,0}lower_bound(trans,0,std::greater<>()).base().base() v{ 1 , 1 , 0 , 0 } // trans v // .base(){{1,'b'},{1,'a'},{0,'b'},{0,'a'}} // rev v // .base() {{0,'a'},{0,'b'},{1,'a'},{1,'b'}}; // vec
.base()
must preserve identity of elementvector<pair<int,char>> vec={{0,'a'},{0,'b'},{1,'a'},{1,'b'}};auto rev=reverse(vec); // {{1,'b'},{1,'a'},{0,'b'},{0,'a'}}
auto trans=transform(rev, mem_fn(&pair<int,char>::first)); // {1,1,0,0}lower_bound(trans,0,std::greater<>()).base().base() | v{ 1 , 1 , 0 , 0 } // trans | v // .base(){{1,'b'},{1,'a'},{0,'b'},{0,'a'}} // rev v | v // .base() {{0,'a'},{0,'b'},{1,'a'},{1,'b'}}; // vec
.base()
must preserve identity of element.base()
must also preserve identity of border
!!! the same base() cannot do both !!!
struct reverse_adaptor { struct iterator { BaseIt m_it; operator++() { --m_it; } operator--() { ++m_it; } operator*() { return *(m_it-1); } // why? }; begin() { return iterator{m_base.end()}; } end() { return iterator{m_base.begin()}; }};
iterator
at begin()
stores m_it=m_base.end()
*(m_base.end()-1)
struct reverse_adaptor { struct iterator { BaseIt m_it; operator++() { --m_it; } operator--() { ++m_it; } operator*() { return *(m_it-1); } // why? }; begin() { return iterator{m_base.end()}; } end() { return iterator{m_base.begin()}; }};
iterator
at begin()
stores m_it=m_base.end()
*(m_base.end()-1)
iterator
at end()
stores m_it=m_base.begin()
struct reverse_adaptor { struct iterator { BaseIt m_it; operator++() { --m_it; } operator--() { ++m_it; } operator*() { return *(m_it-1); } // why? }; begin() { return iterator{m_base.end()}; } end() { return iterator{m_base.begin()}; }};
iterator
at begin()
stores m_it=m_base.end()
*(m_base.end()-1)
iterator
at end()
stores m_it=m_base.begin()
iterator
to end()-1
makes m_it=m_base.begin()+1
*(m_base.begin()+1-1)
- OK!struct reverse_adaptor { struct iterator { BaseIt m_it; operator++() { --m_it; } operator--() { ++m_it; } operator*() { return *(m_it-1); } base() { return m_it-1; } // correct for element base() { return m_it; } // correct for border }; begin() { return iterator{m_base.end()}; } end() { return iterator{m_base.begin()}; }};
reverse
sequence is element before border in original sequence | v{ b , c , a , d } v // .base() { a , b , c , d }
base()
of element well-definedbase()
of border in general undefinedsort
adaptorreverse
adaptorbase()
of border well-defined, but different from base()
of elementborder_base
and element_base
base()
always does right thingQ: Do Iterators really have assigned roles Border/Element?
Q: Do Iterators really have assigned roles Border/Element?
find
Q: Do Iterators really have assigned roles Border/Element?
lower_bound
Q: Do Iterators really have assigned roles Border/Element?
lower_bound
upper_bound
Q: Do Iterators really have assigned roles Border/Element?
lower_bound
upper_bound
-> Iterator instances have distinct roles Border/Element
auto it=find(rng, t);if(it!=end(rng)) {...}
end()
's meaning depends on roleif( auto it=find(rng, t) ) {...}
-> Introduce Border and Element concepts!
begin end | v | v | v | v | { a , b , c , d }
|
: like Iterator butelement_before()
element_after()
begin()
and end()
are borders<algorithm>
are bordersbegin end | v | v | v | v | { a , b , c , d }
|
: like Iterator butelement_before()
element_after()
begin()
and end()
are borders<algorithm>
are bordersbegin end | v | v | v | v | { a , b , c , d }
|
: like Iterator butelement_before()
element_after()
begin()
and end()
are borders<algorithm>
are borders<algorithm>
mismatch // end of matching prefixsearch // begin of matching rangelower_bound // begin of equal rangeupper_bound // end of equal rangeequal_range // lower and upper bound togetherpartition_point/[stable_]partition // border between first part // and second partunique // end of compacted range
begin end | v | v | v | v | { a , b , c , d }
v
: like Iterator butend()
, cannot ++
beyond last elementborder_before()
/border_after()
following algorithms return element:
[max_|min_]element // max/min element of a range
range_of_elements
utility to get all elements inside borders
for_each( range_of_elements(range), [&]( auto element ){...} );
null
state reached through value initialization Element{}
null
instead of .end()
Element elem{}; // null elementassert(!elem);if( auto it=find_unique(rng, t) ) {...}
std::find[_if]
gets refined totc::find_unique[_if] -> Elementtc::find_first[_if] -> Elementtc::find_last[_if] -> Elementtc::trim_left[_if] -> Bordertc::trim_right[_if] -> Border
std::lower_bound
gets refined totc::binary_find_unique -> Elementtc::binary_find_first -> Elementtc::binary_find_last -> Elementtc::lower_bound -> Border
std::find[_if]
gets refined totc::find_unique[_if] -> Elementtc::find_first[_if] -> Elementtc::find_last[_if] -> Elementtc::trim_left[_if] -> Bordertc::trim_right[_if] -> Border
std::lower_bound
gets refined totc::binary_find_unique -> Elementtc::binary_find_first -> Elementtc::binary_find_last -> Elementtc::lower_bound -> Border
border_before()
/border_after()
to convert Element to Borderstd::find[_if]
gets refined totc::find_unique[_if] -> Elementtc::find_first[_if] -> Elementtc::find_last[_if] -> Elementtc::trim_left[_if] -> Bordertc::trim_right[_if] -> Border
std::lower_bound
gets refined totc::binary_find_unique -> Elementtc::binary_find_first -> Elementtc::binary_find_last -> Elementtc::lower_bound -> Border
border_before()
/border_after()
to convert Element to Border_unique
functions assert single matchif( auto it=find_unique(rng, t) ) {...}
rng
only once// return borderlower_bound<return_border> -> border// return view beginning/ending at borderlower_bound<return_take> -> viewlower_bound<return_drop> -> view// return border's adjacent elementlower_bound<return_element_after> -> elementupper_bound<return_element_before> -> element
// return element, which may not be therefind<return_element_or_null>// return element, which must be therefind<return_element>// return element's adjacent border [or alternative if not there]find<return_border_before[_or_begin|_or_end]>find<return_border_after[_or_begin|_or_end]>// return view beginning/ending adjacent to element// [or alternative if not there]find<return_take_before[_or_empty|_or_all]>find<return_take_after[_or_empty|_or_all]>find<return_drop_before[_or_empty|_or_all]>find<return_drop_after[_or_empty|_or_all]>
template< typename Rng >struct return_take_before_or_empty { template<typename It> static auto pack_element(It it, Rng&& rng) noexcept { return tc::take(std::forward<Rng>(rng), it); } static auto pack_no_element(Rng&& rng) noexcept { return tc::take(std::forward<Rng>(rng), boost::begin(rng)); }};
THANK YOU!
Keyboard shortcuts
↑, ←, Pg Up, k | Go to previous slide |
↓, →, Pg Dn, Space, j | Go to next slide |
Home | Go to first slide |
End | Go to last slide |
b / m / f | Toggle blackout / mirrored / fullscreen mode |
c | Clone slideshow |
p | Toggle presenter mode |
t | Restart the presentation timer |
?, h | Toggle this help |
Esc | Back to slideshow |