SlideShare a Scribd company logo
1 of 94
Versatile C++
Mikhail Matrosov, Expert Software Engineer, Align Technology
x
y
Mikhail Matrosov, Versatile C++, CoreHard 2018 2
x
y
Mikhail Matrosov, Versatile C++, CoreHard 2018 3
Mikhail Matrosov, Versatile C++, CoreHard 2018 4
0 1 2 3 4 5 6 1 2 3 4
0 1 2 3 4 5 6
0 1 2 3 4 5 6 4 5 6 0 1
Mikhail Matrosov, Versatile C++, CoreHard 2018 5
≈
≈
≈
≈
≈
≈
≈
Mikhail Matrosov, Versatile C++, CoreHard 2018 6
1)
2)
3)
4)
5)
6)
7)
8)
Mikhail Matrosov, Versatile C++, CoreHard 2018 7
[
[[
[
[
[
[
[
1)
2)
3)
4)
5)
6)
7)
8)
Mikhail Matrosov, Versatile C++, CoreHard 2018 8
[ )
[ )[
[ )
[ )
[ )
[ )
[)
)
1)
2)
3)
4)
5)
6)
7)
8)
Mikhail Matrosov, Versatile C++, CoreHard 2018 9
[ )
[ ) [[
[ ) [
[ )
[ ) [
[ )[
[)[
[
)[
[
1)
2)
3)
4)
5)
6)
7)
8)
Mikhail Matrosov, Versatile C++, CoreHard 2018 10
[ )
[ ) [[
[ ) [
[ )
[ ) [ )
[ )[)
[)[)
[)
)[)
)
[)
)
1)
2)
3)
4)
5)
6)
7)
8)
Mikhail Matrosov, Versatile C++, CoreHard 2018 11
struct Point
{
int x;
int y;
};
bool isPositive(const Point& pt)
{
return pt.x >= 0;
};
Mikhail Matrosov, Versatile C++, CoreHard 2018 12
std::vector<Point> extract(const std::vector<Point>& points)
{
Mikhail Matrosov, Versatile C++, CoreHard 2018 13
std::vector<Point> extract(const std::vector<Point>& points)
{
auto begin1 = std::find_if (points.begin(), points.end(), isPositive);
[
Mikhail Matrosov, Versatile C++, CoreHard 2018 14
std::vector<Point> extract(const std::vector<Point>& points)
{
auto begin1 = std::find_if (points.begin(), points.end(), isPositive);
auto end1 = std::find_if_not(begin1, points.end(), isPositive);
[ )
Mikhail Matrosov, Versatile C++, CoreHard 2018 15
std::vector<Point> extract(const std::vector<Point>& points)
{
auto begin1 = std::find_if (points.begin(), points.end(), isPositive);
auto end1 = std::find_if_not(begin1, points.end(), isPositive);
auto begin2 = std::find_if (end1, points.end(), isPositive);
[ ) [
Mikhail Matrosov, Versatile C++, CoreHard 2018 16
std::vector<Point> extract(const std::vector<Point>& points)
{
auto begin1 = std::find_if (points.begin(), points.end(), isPositive);
auto end1 = std::find_if_not(begin1, points.end(), isPositive);
auto begin2 = std::find_if (end1, points.end(), isPositive);
auto end2 = std::find_if_not(begin2, points.end(), isPositive);
[ ) [ )
Mikhail Matrosov, Versatile C++, CoreHard 2018 17
std::vector<Point> extract(const std::vector<Point>& points)
{
auto begin1 = std::find_if (points.begin(), points.end(), isPositive);
auto end1 = std::find_if_not(begin1, points.end(), isPositive);
auto begin2 = std::find_if (end1, points.end(), isPositive);
auto end2 = std::find_if_not(begin2, points.end(), isPositive);
if (!(begin2 == end2 || begin1 == points.begin() && end2 == points.end()))
throw std::runtime_error("Unexpected order");
[ ) [ )
Mikhail Matrosov, Versatile C++, CoreHard 2018 18
std::vector<Point> extract(const std::vector<Point>& points)
{
auto begin1 = std::find_if (points.begin(), points.end(), isPositive);
auto end1 = std::find_if_not(begin1, points.end(), isPositive);
auto begin2 = std::find_if (end1, points.end(), isPositive);
auto end2 = std::find_if_not(begin2, points.end(), isPositive);
if (!(begin2 == end2 || begin1 == points.begin() && end2 == points.end()))
throw std::runtime_error("Unexpected order");
std::vector<Point> result;
result.reserve((end1 - begin1) + (end2 - begin2));
[ ) [ )
Mikhail Matrosov, Versatile C++, CoreHard 2018 19
std::vector<Point> extract(const std::vector<Point>& points)
{
auto begin1 = std::find_if (points.begin(), points.end(), isPositive);
auto end1 = std::find_if_not(begin1, points.end(), isPositive);
auto begin2 = std::find_if (end1, points.end(), isPositive);
auto end2 = std::find_if_not(begin2, points.end(), isPositive);
if (!(begin2 == end2 || begin1 == points.begin() && end2 == points.end()))
throw std::runtime_error("Unexpected order");
std::vector<Point> result;
result.reserve((end1 - begin1) + (end2 - begin2));
result.insert(result.end(), begin2, end2);
result.insert(result.end(), begin1, end1);
[ ) [ )
Mikhail Matrosov, Versatile C++, CoreHard 2018 20
std::vector<Point> extract(const std::vector<Point>& points)
{
auto begin1 = std::find_if (points.begin(), points.end(), isPositive);
auto end1 = std::find_if_not(begin1, points.end(), isPositive);
auto begin2 = std::find_if (end1, points.end(), isPositive);
auto end2 = std::find_if_not(begin2, points.end(), isPositive);
if (!(begin2 == end2 || begin1 == points.begin() && end2 == points.end()))
throw std::runtime_error("Unexpected order");
std::vector<Point> result;
result.reserve((end1 - begin1) + (end2 - begin2));
result.insert(result.end(), begin2, end2);
result.insert(result.end(), begin1, end1);
return result;
} [ ) [ )
Mikhail Matrosov, Versatile C++, CoreHard 2018 21
Mikhail Matrosov, Versatile C++, CoreHard 2018 22
std::vector<Point> extract(std::vector<Point>&& points)
{
Mikhail Matrosov, Versatile C++, CoreHard 2018 23
std::vector<Point> extract(std::vector<Point>&& points)
{
auto begin1 = std::find_if (points.begin(), points.end(), isPositive);
auto end1 = std::find_if_not(begin1, points.end(), isPositive);
auto begin2 = std::find_if (end1, points.end(), isPositive);
auto end2 = std::find_if_not(begin2, points.end(), isPositive);
if (!(begin2 == end2 || begin1 == points.begin() && end2 == points.end()))
throw std::runtime_error("Unexpected order");
Mikhail Matrosov, Versatile C++, CoreHard 2018 24
std::vector<Point> extract(std::vector<Point>&& points)
{
auto begin1 = std::find_if (points.begin(), points.end(), isPositive);
auto end1 = std::find_if_not(begin1, points.end(), isPositive);
auto begin2 = std::find_if (end1, points.end(), isPositive);
auto end2 = std::find_if_not(begin2, points.end(), isPositive);
if (!(begin2 == end2 || begin1 == points.begin() && end2 == points.end()))
throw std::runtime_error("Unexpected order");
gather(points.begin(), points.end(), begin1, end1, begin2, end2);
0 1 2 3 4 5 6 7 0 1 25 6 7 ? ?
gather
0 1 2 3 4 5 6 7 4 5 ?2 3 ? ?
gather
?
Mikhail Matrosov, Versatile C++, CoreHard 2018 25
std::vector<Point> extract(std::vector<Point>&& points)
{
auto begin1 = std::find_if (points.begin(), points.end(), isPositive);
auto end1 = std::find_if_not(begin1, points.end(), isPositive);
auto begin2 = std::find_if (end1, points.end(), isPositive);
auto end2 = std::find_if_not(begin2, points.end(), isPositive);
if (!(begin2 == end2 || begin1 == points.begin() && end2 == points.end()))
throw std::runtime_error("Unexpected order");
gather(points.begin(), points.end(), begin1, end1, begin2, end2);
points.resize((end1 - begin1) + (end2 - begin2));
Mikhail Matrosov, Versatile C++, CoreHard 2018 26
std::vector<Point> extract(std::vector<Point>&& points)
{
auto begin1 = std::find_if (points.begin(), points.end(), isPositive);
auto end1 = std::find_if_not(begin1, points.end(), isPositive);
auto begin2 = std::find_if (end1, points.end(), isPositive);
auto end2 = std::find_if_not(begin2, points.end(), isPositive);
if (!(begin2 == end2 || begin1 == points.begin() && end2 == points.end()))
throw std::runtime_error("Unexpected order");
gather(points.begin(), points.end(), begin1, end1, begin2, end2);
points.resize((end1 - begin1) + (end2 - begin2));
return std::move(points);
}
Mikhail Matrosov, Versatile C++, CoreHard 2018 27
Mikhail Matrosov, Versatile C++, CoreHard 2018 28
Never apply std::move
after return…
Always apply std::move
on r-value references!
c++11 Return value
optimization or move?
template<class It>
void gather(It first, It last, It begin1, It end1, It begin2, It end2)
{
assert(begin2 == end2 || begin1 == first && end2 == last);
Mikhail Matrosov, Versatile C++, CoreHard 2018 29
0 1 2 3 4 5 6 7 0 1 25 6 7 ? ?
gather
0 1 2 3 4 5 6 7 4 5 ?2 3 ? ?
gather
?
first
end2begin2
last
end1begin1
middlefirst
end2
begin2
last
end1
middle
begin1
template<class It>
void gather(It first, It last, It begin1, It end1, It begin2, It end2)
{
assert(begin2 == end2 || begin1 == first && end2 == last);
auto middle = begin2 == end2 ? begin1 : begin2;
std::rotate(first, middle, last);
}
0 1 2 3 4 5 6 70 1 2 3 4 5 6 7
Mikhail Matrosov, Versatile C++, CoreHard 2018 30
220≈1M
1/4 1/41/2
31Mikhail Matrosov, Versatile C++, CoreHard 2018
Mikhail Matrosov, Versatile C++, CoreHard 2018 32
/usr/bin/clang++
-- broken
cmake ../
sudo update-alternatives
--list clang
/usr/bin/clang++-6.0
-stdlib=libc++ -v
Selected GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/7.3.0
Candidate multilib: .;@m64
Selected multilib: .;@m64
clang -cc1 version 6.0.0 based upon LLVM 6.0.0 default target x86_64-pc-linux-gnu
ignoring nonexistent directory "/include"
ignoring duplicate directory "/usr/include/clang/6.0.0/include"
#include "..." search starts here:
#include <...> search starts here:
/usr/include/c++/v1
/usr/include/clang/6.0.0/include
/usr/local/include
/usr/include/x86_64-linux-gnu
/usr/include
End of search list.
../../clang_test/hello.cpp:2:10: fatal error: 'experimental/generator' file not found
#include <experimental/generator>
^~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.
# of
segments?
At the
beginning?
Enough
room?
Nothing
to do!
Fall back to
rotate()
Move to
front!
Move
both!
One Two
Yes
No
Yes
No
Mikhail Matrosov, Versatile C++, CoreHard 2018 34
template<class It>
void gather(It first, It last, It begin1, It end1, It begin2, It end2)
{
assert(begin2 == end2 || begin1 == first && end2 == last);
if (begin2 == end2) {
if (begin1 != first)
std::move(begin1, end1, first); // Like std::copy(), but moves elements
return;
}
auto len2 = std::distance(begin2, end2); // Better for generic code
auto lenFree = std::distance(end1, begin2);
if (len2 <= lenFree) {
auto len1 = std::distance(begin1, end1);
std::move_backward(begin1, end1, first + len1 + len2);
std::move(begin2, end2, first);
return;
}
std::rotate(first, begin2, last);
}
0 1 2 3 4
35
Mikhail Matrosov, Versatile C++, CoreHard 2018 36
Mikhail Matrosov, Versatile C++, CoreHard 2018 37
std::list<Point> extract(std::list<Point>&& points)
{
Mikhail Matrosov, Versatile C++, CoreHard 2018 38
std::list<Point> extract(std::list<Point>&& points)
{
auto begin1 = std::find_if (points.begin(), points.end(), isPositive);
auto end1 = std::find_if_not(begin1, points.end(), isPositive);
auto begin2 = std::find_if (end1, points.end(), isPositive);
auto end2 = std::find_if_not(begin2, points.end(), isPositive);
if (!(begin2 == end2 || begin1 == points.begin() && end2 == points.end()))
throw std::runtime_error("Unexpected order");
Mikhail Matrosov, Versatile C++, CoreHard 2018 39
std::list<Point> extract(std::list<Point>&& points)
{
auto begin1 = std::find_if (points.begin(), points.end(), isPositive);
auto end1 = std::find_if_not(begin1, points.end(), isPositive);
auto begin2 = std::find_if (end1, points.end(), isPositive);
auto end2 = std::find_if_not(begin2, points.end(), isPositive);
if (!(begin2 == end2 || begin1 == points.begin() && end2 == points.end()))
throw std::runtime_error("Unexpected order");
points.erase(points.begin(), begin1);
points.splice(points.begin(), points, begin2, end2);
points.erase(end1, points.end());
return std::move(points);
}
Mikhail Matrosov, Versatile C++, CoreHard 2018 40
points.erase(points.begin(), begin1);
points.splice(points.begin(), points, begin2, end2);
points.erase(end1, points.end());
2 3 4 5 6 7
0 1 2 3 4 5 6 7
list 0 1
list
Mikhail Matrosov, Versatile C++, CoreHard 2018 41
Mikhail Matrosov, Versatile C++, CoreHard 2018 42
YOU WERE THE CHOSEN ONE!
std::list
43
auto extract(const std::vector<Point>& points)
{
auto begin1 = std::find_if (points.begin(), points.end(), isPositive);
auto end1 = std::find_if_not(begin1, points.end(), isPositive);
auto begin2 = std::find_if (end1, points.end(), isPositive);
auto end2 = std::find_if_not(begin2, points.end(), isPositive);
if (!(begin2 == end2 || begin1 == points.begin() && end2 == points.end()))
throw std::runtime_error("Unexpected order");
Mikhail Matrosov, Versatile C++, CoreHard 2018 44
auto extract(const std::vector<Point>& points)
{
auto begin1 = std::find_if (points.begin(), points.end(), isPositive);
auto end1 = std::find_if_not(begin1, points.end(), isPositive);
auto begin2 = std::find_if (end1, points.end(), isPositive);
auto end2 = std::find_if_not(begin2, points.end(), isPositive);
if (!(begin2 == end2 || begin1 == points.begin() && end2 == points.end()))
throw std::runtime_error("Unexpected order");
return boost::join(boost::make_iterator_range(begin2, end2),
boost::make_iterator_range(begin1, end1));
}
Mikhail Matrosov, Versatile C++, CoreHard 2018 45
46Mikhail Matrosov, Versatile C++, CoreHard 2018
47
template<class It>
class WrappingIterator : public boost::iterator_facade<WrappingIterator<It>,
typename It::value_type,
boost::random_access_traversal_tag,
typename It::reference>
{
public:
WrappingIterator() = default;
WrappingIterator(It it, It begin, It end) :
m_begin(begin), m_size(end - begin), m_offset(it - begin) {}
template <class OtherIt>
WrappingIterator(const WrappingIterator<OtherIt>& other) :
m_begin(other.m_begin), m_size(other.m_size), m_offset(other.m_offset) {}
private:
friend class boost::iterator_core_access;
template<class> friend class WrappingIterator;
using Base = boost::iterator_facade<WrappingIterator<It>,
typename It::value_type,
boost::random_access_traversal_tag,
typename It::reference>;
// Core interface functions (on the next slide)
It m_begin;
size_t m_size;
size_t m_offset;
};
48
typename Base::reference dereference() const
{
return *(m_begin + (m_offset < m_size ? m_offset : m_offset - m_size));
}
template <class OtherIt>
bool equal(const WrappingIterator<OtherIt>& other) const
{
assert(other.m_begin == m_begin && other.m_size == m_size);
return other.m_offset == m_offset;
}
void advance(typename Base::difference_type n)
{
m_offset += n;
}
void increment()
{
++m_offset;
}
void decrement()
{
--m_offset;
}
template <class OtherIt>
typename Base::difference_type distance_to(const WrappingIterator<OtherIt>& other) const
{
assert(other.m_begin == m_begin && other.m_size == m_size);
return other.m_offset - m_offset;
}
49Mikhail Matrosov, Versatile C++, CoreHard 2018
auto extract(const std::vector<Point>& points)
{
auto begin1 = std::find_if (points.begin(), points.end(), isPositive);
auto end1 = std::find_if_not(begin1, points.end(), isPositive);
auto begin2 = std::find_if (end1, points.end(), isPositive);
auto end2 = std::find_if_not(begin2, points.end(), isPositive);
if (!(begin2 == end2 || begin1 == points.begin() && end2 == points.end()))
throw std::runtime_error("Unexpected order");
return boost::join(boost::make_iterator_range(begin2, end2),
boost::make_iterator_range(begin1, end1));
}
Mikhail Matrosov, Versatile C++, CoreHard 2018 50
template<class It>
auto extract(const std::vector<Point>& points)
{
auto begin1 = std::find_if (points.begin(), points.end(), isPositive);
auto end1 = std::find_if_not(begin1, points.end(), isPositive);
auto begin2 = std::find_if (end1, points.end(), isPositive);
auto end2 = std::find_if_not(begin2, points.end(), isPositive);
if (!(begin2 == end2 || begin1 == points.begin() && end2 == points.end()))
throw std::runtime_error("Unexpected order");
return boost::join(boost::make_iterator_range(begin2, end2),
boost::make_iterator_range(begin1, end1));
}
Mikhail Matrosov, Versatile C++, CoreHard 2018 51
template<class It>
auto extract(It first, It last)
{
auto begin1 = std::find_if (points.begin(), points.end(), isPositive);
auto end1 = std::find_if_not(begin1, points.end(), isPositive);
auto begin2 = std::find_if (end1, points.end(), isPositive);
auto end2 = std::find_if_not(begin2, points.end(), isPositive);
if (!(begin2 == end2 || begin1 == points.begin() && end2 == points.end()))
throw std::runtime_error("Unexpected order");
return boost::join(boost::make_iterator_range(begin2, end2),
boost::make_iterator_range(begin1, end1));
}
Mikhail Matrosov, Versatile C++, CoreHard 2018 52
template<class It>
auto extract(It first, It last)
{
auto begin1 = std::find_if (first, last, isPositive);
auto end1 = std::find_if_not(begin1, last, isPositive);
auto begin2 = std::find_if (end1, last, isPositive);
auto end2 = std::find_if_not(begin2, last, isPositive);
if (!(begin2 == end2 || begin1 == first && end2 == last))
throw std::runtime_error("Unexpected order");
return boost::join(boost::make_iterator_range(begin2, end2),
boost::make_iterator_range(begin1, end1));
}
Mikhail Matrosov, Versatile C++, CoreHard 2018 53
template<class It>
auto extract(It first, It last)
{
It begin1 = std::find_if (first, last, isPositive);
It end1 = std::find_if_not(begin1, last, isPositive);
It begin2 = std::find_if (end1, last, isPositive);
It end2 = std::find_if_not(begin2, last, isPositive);
if (!(begin2 == end2 || begin1 == first && end2 == last))
throw std::runtime_error("Unexpected order");
return boost::join(boost::make_iterator_range(begin2, end2),
boost::make_iterator_range(begin1, end1));
}
Mikhail Matrosov, Versatile C++, CoreHard 2018 54
template<class It, class Predicate>
auto extract(It first, It last, Predicate p)
{
It begin1 = std::find_if (first, last, p);
It end1 = std::find_if_not(begin1, last, p);
It begin2 = std::find_if (end1, last, p);
It end2 = std::find_if_not(begin2, last, p);
if (!(begin2 == end2 || begin1 == first && end2 == last))
throw std::runtime_error("Unexpected order");
return boost::join(boost::make_iterator_range(begin2, end2),
boost::make_iterator_range(begin1, end1));
}
Mikhail Matrosov, Versatile C++, CoreHard 2018 55
template<class It, class Predicate>
auto extract(It first, It last, Predicate p)
{
It begin1 = std::find_if (first, last, p);
It end1 = std::find_if_not(begin1, last, p);
It begin2 = std::find_if (end1, last, p);
It end2 = std::find_if_not(begin2, last, p);
if (!(begin2 == end2 || begin1 == first && end2 == last))
throw std::runtime_error("Unexpected order");
return boost::join(boost::make_iterator_range(begin2, end2),
boost::make_iterator_range(begin1, end1));
}
Mikhail Matrosov, Versatile C++, CoreHard 2018 56
57Mikhail Matrosov, Versatile C++, CoreHard 2018
template<class It, class Predicate>
auto extract(It first, It last, Predicate p)
{
It begin1 = std::find_if (first, last, p);
It end1 = std::find_if_not(begin1, last, p);
It begin2 = std::find_if (end1, last, p);
It end2 = std::find_if_not(begin2, last, p);
if (!(begin2 == end2 || begin1 == first && end2 == last))
throw std::runtime_error("Unexpected order");
return boost::join(boost::make_iterator_range(begin2, end2),
boost::make_iterator_range(begin1, end1));
}
Mikhail Matrosov, Versatile C++, CoreHard 2018 58
template<class It, class Predicate>
auto extract(It first, It last, Predicate p)
{
It begin1 = std::find_if (first, last, p);
It end1 = std::find_if_not(begin1, last, p);
It begin2 = std::find_if (end1, last, p);
It end2 = std::find_if_not(begin2, last, p);
if (!(begin2 == end2 || begin1 == first && end2 == last))
throw std::runtime_error("Unexpected order");
return ranges::view::concat(ranges::range<It>(begin2, end2),
ranges::range<It>(begin1, end1));
}
Mikhail Matrosov, Versatile C++, CoreHard 2018 59
60Mikhail Matrosov, Versatile C++, CoreHard 2018
#include <experimental/generator>
namespace std
{
using std::experimental::generator;
}
// For VC++ compile with /await
Coroutines!
61Mikhail Matrosov, Versatile C++, CoreHard 2018
// Not a generic function, since compilers at the moment
// may have troubles with template coroutines
std::generator<Point> extract(const std::vector<Point>& points)
{
auto begin1 = std::find_if (points.begin(), points.end(), isPositive);
auto end1 = std::find_if_not(begin1, points.end(), isPositive);
auto begin2 = std::find_if (end1, points.end(), isPositive);
auto end2 = std::find_if_not(begin2, points.end(), isPositive);
if (!(begin2 == end2 || begin1 == points.begin() && end2 == points.end()))
throw std::runtime_error("Unexpected order");
for (auto it = begin2; it != end2; ++it) co_yield *it;
for (auto it = begin1; it != end1; ++it) co_yield *it;
}
// Used just as ranges:
// std::generator provides begin() and end() methods returning input iterators
Mikhail Matrosov, Versatile C++, CoreHard 2018 62
63Mikhail Matrosov, Versatile C++, CoreHard 2018
“C++ Coroutines - a negative
overhead abstraction”
64
Mikhail Matrosov, Versatile C++, CoreHard 2018 65
template<class It, class Predicate>
auto extract(It first, It last, Predicate p)
{
It begin1 = std::find_if (first, last, p);
It end1 = std::find_if_not(begin1, last, p);
It begin2 = std::find_if (end1, last, p);
It end2 = std::find_if_not(begin2, last, p);
if (!(begin2 == end2 || begin1 == first && end2 == last))
throw std::runtime_error("Unexpected order");
return boost::join(boost::make_iterator_range(begin2, end2),
boost::make_iterator_range(begin1, end1));
}
Mikhail Matrosov, Versatile C++, CoreHard 2018 66
template<class It, class Predicate>
auto extract(It first, It last, Predicate p)
{
It begin1 = std::find_if (first, last, p);
It end1 = std::find_if_not(begin1, last, p);
It begin2 = std::find_if (end1, last, p);
It end2 = last;
if (!(begin2 == end2 || begin1 == first && end2 == last))
throw std::runtime_error("Unexpected order");
return boost::join(boost::make_iterator_range(begin2, end2),
boost::make_iterator_range(begin1, end1));
}
Mikhail Matrosov, Versatile C++, CoreHard 2018 67
template<class It, class Predicate>
auto extract(It first, It last, Predicate p)
{
It begin1 = std::find_if (first, last, p);
It end1 = std::find_if_not(begin1, last, p);
It begin2 = std::find_if (end1, last, p);
It end2 = last;
assert(end2 == std::find_if_not(begin2, last, p) &&
(begin2 == end2 || begin1 == first && end2 == last));
return boost::join(boost::make_iterator_range(begin2, end2),
boost::make_iterator_range(begin1, end1));
}
Mikhail Matrosov, Versatile C++, CoreHard 2018 68
69Mikhail Matrosov, Versatile C++, CoreHard 2018
template<class It, class Predicate>
auto extract(It first, It last, Predicate p)
{
It begin1 = std::find_if (first, last, p);
It end1 = std::find_if_not(begin1, last, p);
It begin2 = std::find_if (end1, last, p);
It end2 = last;
assert(end2 == std::find_if_not(begin2, last, p) &&
(begin2 == end2 || begin1 == first && end2 == last));
return boost::join(boost::make_iterator_range(begin2, end2),
boost::make_iterator_range(begin1, end1));
} 70
template<class It>
struct Bounds
{
It begin1, end1, begin2, end2;
};
template<class It, class Predicate>
Bounds<It> findBounds(It first, It last, Predicate p)
{
It begin1 = std::find_if (first, last, p);
It end1 = std::find_if_not(begin1, last, p);
It begin2 = std::find_if (end1, last, p);
return { begin1, end1, begin2, last };
}
template<class It, class Predicate>
auto extract(It first, It last, Predicate p)
{
auto bounds = findBounds(first, last, p);
return boost::join(boost::make_iterator_range(bounds.begin2, bounds.end2),
boost::make_iterator_range(bounds.begin1, bounds.end1));
} 71
72Mikhail Matrosov, Versatile C++, CoreHard 2018
All negative All positive
All negativeAll positive
73Mikhail Matrosov, Versatile C++, CoreHard 2018
74Mikhail Matrosov, Versatile C++, CoreHard 2018
All positive All negative
All positiveAll negative
75Mikhail Matrosov, Versatile C++, CoreHard 2018
template<class It, class Predicate>
Bounds<It> findBounds(It first, It last, Predicate p)
{
Bounds<It> bounds = { first, last, last, last }; // Whole sequence by default
if (first == last)
return bounds;
if (!p(*first) || !p(last[-1]))
{
// One segment, or empty
It sample = findAny(first, last, p);
bounds.begin1 = std::partition_point(first, sample, std::not_fn(p));
bounds.end1 = std::partition_point(sample, last, p);
}
else if (It hole = findAny(first, last, std::not_fn(p)); hole != last)
{
// Two segments
bounds.end1 = std::partition_point(first, hole, p);
bounds.begin2 = std::partition_point(hole, last, std::not_fn(p));
}
return bounds;
}
76
10 32 54 76 98 1110
8
4
9
2
10
5
11
1
6
12
7
3
Take element in the middle, then recurse to left and
right
77Mikhail Matrosov, Versatile C++, CoreHard 2018
10 32 54 76 98 1110
8
4
9
2
10
5
11
1
6
12
7
3
Take element in the middle, then recurse to left and
right
78
Level First index Distances to next
1 6
2 3 6
3 1 4, 3, 3
4 0 2, 2, 3, 3
Mikhail Matrosov, Versatile C++, CoreHard 2018
10 32 54 76 98 1110 1312 14
8
4
9
2
10
5
11
1
12
6
13
3
14
7
15
Take element in the middle, then recurse to left and
right
79Mikhail Matrosov, Versatile C++, CoreHard 2018
10 32 54 76 98 1110 1312 14
8
4
9
2
10
5
11
1
12
6
13
3
14
7
15
Level First index Distances to next
1 7
2 3 8
3 1 4, 4, 4
4 0 2, 2, 2, 2, 2, 2, 2
Take element in the middle, then recurse to left and
right
80Mikhail Matrosov, Versatile C++, CoreHard 2018
10 32 54 76 98 1110
7
4
8
2
9
5
10
1
11
6
12
3
Repeat as if it was for the power of
two
81Mikhail Matrosov, Versatile C++, CoreHard 2018
10 32 54 76 98 1110
7
4
8
2
9
5
10
1
11
6
12
3
Level First index Distances to next
1 7
2 3 8
3 1 4, 4
4 0 2, 2, 2, 2, 2
82Mikhail Matrosov, Versatile C++, CoreHard 2018
Repeat as if it was for the power of
two
template<class It, class Predicate> // It is RandomAccess
It findAny(It first, It last, Predicate p)
{
using diff_t = typename std::iterator_traits<It>::difference_type;
diff_t n = last - first;
diff_t step = 1;
while (step <= n)
step *= 2;
while (step > 1)
{
for (diff_t i = step / 2 - 1; i < n; i += step)
if (p(first[i]))
return first + i;
step /= 2;
}
return last;
}
83
84Mikhail Matrosov, Versatile C++, CoreHard 2018
template<class It, class Predicate>
Bounds<It> findBounds(It first, It last, Predicate p, std::forward_iterator_tag)
{
// No checks
}
template<class It, class Predicate>
Bounds<It> findBounds(It first, It last, Predicate p, std::random_access_iterator_tag)
{
// No checks smart
}
template<class It, class Predicate>
Bounds<It> findBounds(It first, It last, Predicate p)
{
return findBounds(first, last, p, std::iterator_traits<It>::iterator_category{});
}
Tag dispatching
Mikhail Matrosov, Versatile C++, CoreHard 2018 85
Mikhail Matrosov, Versatile C++, CoreHard 2018 86
Computational complexity
•
87Mikhail Matrosov, Versatile C++, CoreHard 2018
88
10 32 54 76 98 1110 1312 1410 32 54 76 98 1110 1312 14
Complexity of findAny()
Mikhail Matrosov, Versatile C++, CoreHard 2018
Computational complexity
•
89Mikhail Matrosov, Versatile C++, CoreHard 2018
•
90Mikhail Matrosov, Versatile C++, CoreHard 2018
None
All
1
2
1/2
1/4
91Mikhail Matrosov, Versatile C++, CoreHard 2018
92Mikhail Matrosov, Versatile C++, CoreHard 2018
Method Input Output
Modify
input
Check
structure
Assume
layout
Copy const vector& vector no yes no
Reuse vector&& vector yes yes no
Reuse smart vector&& vector yes yes no
Reuse std::list list&& list yes yes no
boost.range vector boost::range::joined_range no yes no
WrappingIterator vector boost::iterator_range<WrappingIterator> no yes no
Generic pair of iterators boost::range::joined_range no yes no
Range-V3-VS2015 pair of iterators ranges::concat_view no yes no
VC++ generator pair of iterators std::generator no yes no
No checks pair of iterators boost::range::joined_range no no no
No checks smart pair of random-
access iterators
boost::range::joined_range no no yes
93Mikhail Matrosov, Versatile C++, CoreHard 2018
Mikhail Matrosov, Versatile C++, CoreHard 2018
Take aways
• Analyze! Keyboard after paper
• Recognize patterns, implement them with standard algorithms
• Think about the interface
• Don’t be afraid to go generic
• Use modern C++
• Care about asymptotic complexity
• Measure performance
94
Questions?

More Related Content

What's hot

Graphics practical lab manual
Graphics practical lab manualGraphics practical lab manual
Graphics practical lab manualVivek Kumar Sinha
 
COMPUTER GRAPHICS LAB MANUAL
COMPUTER GRAPHICS LAB MANUALCOMPUTER GRAPHICS LAB MANUAL
COMPUTER GRAPHICS LAB MANUALVivek Kumar Sinha
 
Technical questions for interview c programming
Technical questions for interview  c programmingTechnical questions for interview  c programming
Technical questions for interview c programmingCHANDAN KUMAR
 
Introduction to AspectJ
Introduction to AspectJIntroduction to AspectJ
Introduction to AspectJmukhtarhudaya
 
Cpd lecture im 207
Cpd lecture im 207Cpd lecture im 207
Cpd lecture im 207Syed Tanveer
 
ماترێکس به‌ کوردی ئارام
ماترێکس به‌ کوردی ئارامماترێکس به‌ کوردی ئارام
ماترێکس به‌ کوردی ئارامAram Jamal
 

What's hot (10)

Graphics practical lab manual
Graphics practical lab manualGraphics practical lab manual
Graphics practical lab manual
 
COMPUTER GRAPHICS LAB MANUAL
COMPUTER GRAPHICS LAB MANUALCOMPUTER GRAPHICS LAB MANUAL
COMPUTER GRAPHICS LAB MANUAL
 
Technical questions for interview c programming
Technical questions for interview  c programmingTechnical questions for interview  c programming
Technical questions for interview c programming
 
Introduction to AspectJ
Introduction to AspectJIntroduction to AspectJ
Introduction to AspectJ
 
Cpd lecture im 207
Cpd lecture im 207Cpd lecture im 207
Cpd lecture im 207
 
Functional C++
Functional C++Functional C++
Functional C++
 
1 d array
1 d array1 d array
1 d array
 
ماترێکس به‌ کوردی ئارام
ماترێکس به‌ کوردی ئارامماترێکس به‌ کوردی ئارام
ماترێکس به‌ کوردی ئارام
 
Pointer level 2
Pointer   level 2Pointer   level 2
Pointer level 2
 
Arrays
ArraysArrays
Arrays
 

Similar to Многогранный С++ на практике

Moony li pacsec-1.8
Moony li pacsec-1.8Moony li pacsec-1.8
Moony li pacsec-1.8PacSecJP
 
ArithmeticOperationsOnMatrix.javaimport java.util.Random; import.pdf
ArithmeticOperationsOnMatrix.javaimport java.util.Random; import.pdfArithmeticOperationsOnMatrix.javaimport java.util.Random; import.pdf
ArithmeticOperationsOnMatrix.javaimport java.util.Random; import.pdfkrram1989
 
Whats new in_csharp4
Whats new in_csharp4Whats new in_csharp4
Whats new in_csharp4Abed Bukhari
 
Getting started cpp full
Getting started cpp   fullGetting started cpp   full
Getting started cpp fullVõ Hòa
 
4Developers 2018: Beyond c++17 (Mateusz Pusz)
4Developers 2018: Beyond c++17 (Mateusz Pusz)4Developers 2018: Beyond c++17 (Mateusz Pusz)
4Developers 2018: Beyond c++17 (Mateusz Pusz)PROIDEA
 
Applying Compiler Techniques to Iterate At Blazing Speed
Applying Compiler Techniques to Iterate At Blazing SpeedApplying Compiler Techniques to Iterate At Blazing Speed
Applying Compiler Techniques to Iterate At Blazing SpeedPascal-Louis Perez
 
Python for Scientific Computing -- Ricardo Cruz
Python for Scientific Computing -- Ricardo CruzPython for Scientific Computing -- Ricardo Cruz
Python for Scientific Computing -- Ricardo Cruzrpmcruz
 
Programming with GUTs
Programming with GUTsProgramming with GUTs
Programming with GUTsKevlin Henney
 
C++20 the small things - Timur Doumler
C++20 the small things - Timur DoumlerC++20 the small things - Timur Doumler
C++20 the small things - Timur Doumlercorehard_by
 
WINSEM2020-21_STS3105_SS_VL2020210500169_Reference_Material_I_15-Feb-2021_L6-...
WINSEM2020-21_STS3105_SS_VL2020210500169_Reference_Material_I_15-Feb-2021_L6-...WINSEM2020-21_STS3105_SS_VL2020210500169_Reference_Material_I_15-Feb-2021_L6-...
WINSEM2020-21_STS3105_SS_VL2020210500169_Reference_Material_I_15-Feb-2021_L6-...MaruMengesha
 
Data Structure in C (Lab Programs)
Data Structure in C (Lab Programs)Data Structure in C (Lab Programs)
Data Structure in C (Lab Programs)Saket Pathak
 
Hypercritical C++ Code Review
Hypercritical C++ Code ReviewHypercritical C++ Code Review
Hypercritical C++ Code ReviewAndrey Karpov
 

Similar to Многогранный С++ на практике (20)

Moony li pacsec-1.8
Moony li pacsec-1.8Moony li pacsec-1.8
Moony li pacsec-1.8
 
Stop Monkeys Fall
Stop Monkeys FallStop Monkeys Fall
Stop Monkeys Fall
 
ArithmeticOperationsOnMatrix.javaimport java.util.Random; import.pdf
ArithmeticOperationsOnMatrix.javaimport java.util.Random; import.pdfArithmeticOperationsOnMatrix.javaimport java.util.Random; import.pdf
ArithmeticOperationsOnMatrix.javaimport java.util.Random; import.pdf
 
Whats new in_csharp4
Whats new in_csharp4Whats new in_csharp4
Whats new in_csharp4
 
Getting started cpp full
Getting started cpp   fullGetting started cpp   full
Getting started cpp full
 
4Developers 2018: Beyond c++17 (Mateusz Pusz)
4Developers 2018: Beyond c++17 (Mateusz Pusz)4Developers 2018: Beyond c++17 (Mateusz Pusz)
4Developers 2018: Beyond c++17 (Mateusz Pusz)
 
Seeing Like Software
Seeing Like SoftwareSeeing Like Software
Seeing Like Software
 
機械学習と自動微分
機械学習と自動微分機械学習と自動微分
機械学習と自動微分
 
Java Basics - Part1
Java Basics - Part1Java Basics - Part1
Java Basics - Part1
 
Applying Compiler Techniques to Iterate At Blazing Speed
Applying Compiler Techniques to Iterate At Blazing SpeedApplying Compiler Techniques to Iterate At Blazing Speed
Applying Compiler Techniques to Iterate At Blazing Speed
 
Python for Scientific Computing -- Ricardo Cruz
Python for Scientific Computing -- Ricardo CruzPython for Scientific Computing -- Ricardo Cruz
Python for Scientific Computing -- Ricardo Cruz
 
Programming with GUTs
Programming with GUTsProgramming with GUTs
Programming with GUTs
 
UNIT 2 LOOP CONTROL.pptx
UNIT 2 LOOP CONTROL.pptxUNIT 2 LOOP CONTROL.pptx
UNIT 2 LOOP CONTROL.pptx
 
C++20 the small things - Timur Doumler
C++20 the small things - Timur DoumlerC++20 the small things - Timur Doumler
C++20 the small things - Timur Doumler
 
Java exercise1
Java exercise1Java exercise1
Java exercise1
 
WINSEM2020-21_STS3105_SS_VL2020210500169_Reference_Material_I_15-Feb-2021_L6-...
WINSEM2020-21_STS3105_SS_VL2020210500169_Reference_Material_I_15-Feb-2021_L6-...WINSEM2020-21_STS3105_SS_VL2020210500169_Reference_Material_I_15-Feb-2021_L6-...
WINSEM2020-21_STS3105_SS_VL2020210500169_Reference_Material_I_15-Feb-2021_L6-...
 
Data Structure in C (Lab Programs)
Data Structure in C (Lab Programs)Data Structure in C (Lab Programs)
Data Structure in C (Lab Programs)
 
PRACTICAL COMPUTING
PRACTICAL COMPUTINGPRACTICAL COMPUTING
PRACTICAL COMPUTING
 
Hypercritical C++ Code Review
Hypercritical C++ Code ReviewHypercritical C++ Code Review
Hypercritical C++ Code Review
 
Relational Operators in C
Relational Operators in CRelational Operators in C
Relational Operators in C
 

More from corehard_by

C++ CoreHard Autumn 2018. Создание пакетов для открытых библиотек через conan...
C++ CoreHard Autumn 2018. Создание пакетов для открытых библиотек через conan...C++ CoreHard Autumn 2018. Создание пакетов для открытых библиотек через conan...
C++ CoreHard Autumn 2018. Создание пакетов для открытых библиотек через conan...corehard_by
 
C++ CoreHard Autumn 2018. Что должен знать каждый C++ программист или Как про...
C++ CoreHard Autumn 2018. Что должен знать каждый C++ программист или Как про...C++ CoreHard Autumn 2018. Что должен знать каждый C++ программист или Как про...
C++ CoreHard Autumn 2018. Что должен знать каждый C++ программист или Как про...corehard_by
 
C++ CoreHard Autumn 2018. Actors vs CSP vs Tasks vs ... - Евгений Охотников
C++ CoreHard Autumn 2018. Actors vs CSP vs Tasks vs ... - Евгений ОхотниковC++ CoreHard Autumn 2018. Actors vs CSP vs Tasks vs ... - Евгений Охотников
C++ CoreHard Autumn 2018. Actors vs CSP vs Tasks vs ... - Евгений Охотниковcorehard_by
 
C++ CoreHard Autumn 2018. Знай свое "железо": иерархия памяти - Александр Титов
C++ CoreHard Autumn 2018. Знай свое "железо": иерархия памяти - Александр ТитовC++ CoreHard Autumn 2018. Знай свое "железо": иерархия памяти - Александр Титов
C++ CoreHard Autumn 2018. Знай свое "железо": иерархия памяти - Александр Титовcorehard_by
 
C++ CoreHard Autumn 2018. Информационная безопасность и разработка ПО - Евген...
C++ CoreHard Autumn 2018. Информационная безопасность и разработка ПО - Евген...C++ CoreHard Autumn 2018. Информационная безопасность и разработка ПО - Евген...
C++ CoreHard Autumn 2018. Информационная безопасность и разработка ПО - Евген...corehard_by
 
C++ CoreHard Autumn 2018. Заглядываем под капот «Поясов по C++» - Илья Шишков
C++ CoreHard Autumn 2018. Заглядываем под капот «Поясов по C++» - Илья ШишковC++ CoreHard Autumn 2018. Заглядываем под капот «Поясов по C++» - Илья Шишков
C++ CoreHard Autumn 2018. Заглядываем под капот «Поясов по C++» - Илья Шишковcorehard_by
 
C++ CoreHard Autumn 2018. Ускорение сборки C++ проектов, способы и последстви...
C++ CoreHard Autumn 2018. Ускорение сборки C++ проектов, способы и последстви...C++ CoreHard Autumn 2018. Ускорение сборки C++ проектов, способы и последстви...
C++ CoreHard Autumn 2018. Ускорение сборки C++ проектов, способы и последстви...corehard_by
 
C++ CoreHard Autumn 2018. Метаклассы: воплощаем мечты в реальность - Сергей С...
C++ CoreHard Autumn 2018. Метаклассы: воплощаем мечты в реальность - Сергей С...C++ CoreHard Autumn 2018. Метаклассы: воплощаем мечты в реальность - Сергей С...
C++ CoreHard Autumn 2018. Метаклассы: воплощаем мечты в реальность - Сергей С...corehard_by
 
C++ CoreHard Autumn 2018. Что не умеет оптимизировать компилятор - Александр ...
C++ CoreHard Autumn 2018. Что не умеет оптимизировать компилятор - Александр ...C++ CoreHard Autumn 2018. Что не умеет оптимизировать компилятор - Александр ...
C++ CoreHard Autumn 2018. Что не умеет оптимизировать компилятор - Александр ...corehard_by
 
C++ CoreHard Autumn 2018. Кодогенерация C++ кроссплатформенно. Продолжение - ...
C++ CoreHard Autumn 2018. Кодогенерация C++ кроссплатформенно. Продолжение - ...C++ CoreHard Autumn 2018. Кодогенерация C++ кроссплатформенно. Продолжение - ...
C++ CoreHard Autumn 2018. Кодогенерация C++ кроссплатформенно. Продолжение - ...corehard_by
 
C++ CoreHard Autumn 2018. Concurrency and Parallelism in C++17 and C++20/23 -...
C++ CoreHard Autumn 2018. Concurrency and Parallelism in C++17 and C++20/23 -...C++ CoreHard Autumn 2018. Concurrency and Parallelism in C++17 and C++20/23 -...
C++ CoreHard Autumn 2018. Concurrency and Parallelism in C++17 and C++20/23 -...corehard_by
 
C++ CoreHard Autumn 2018. Обработка списков на C++ в функциональном стиле - В...
C++ CoreHard Autumn 2018. Обработка списков на C++ в функциональном стиле - В...C++ CoreHard Autumn 2018. Обработка списков на C++ в функциональном стиле - В...
C++ CoreHard Autumn 2018. Обработка списков на C++ в функциональном стиле - В...corehard_by
 
C++ Corehard Autumn 2018. Обучаем на Python, применяем на C++ - Павел Филонов
C++ Corehard Autumn 2018. Обучаем на Python, применяем на C++ - Павел ФилоновC++ Corehard Autumn 2018. Обучаем на Python, применяем на C++ - Павел Филонов
C++ Corehard Autumn 2018. Обучаем на Python, применяем на C++ - Павел Филоновcorehard_by
 
C++ CoreHard Autumn 2018. Asynchronous programming with ranges - Ivan Čukić
C++ CoreHard Autumn 2018. Asynchronous programming with ranges - Ivan ČukićC++ CoreHard Autumn 2018. Asynchronous programming with ranges - Ivan Čukić
C++ CoreHard Autumn 2018. Asynchronous programming with ranges - Ivan Čukićcorehard_by
 
C++ CoreHard Autumn 2018. Debug C++ Without Running - Anastasia Kazakova
C++ CoreHard Autumn 2018. Debug C++ Without Running - Anastasia KazakovaC++ CoreHard Autumn 2018. Debug C++ Without Running - Anastasia Kazakova
C++ CoreHard Autumn 2018. Debug C++ Without Running - Anastasia Kazakovacorehard_by
 
C++ CoreHard Autumn 2018. Полезный constexpr - Антон Полухин
C++ CoreHard Autumn 2018. Полезный constexpr - Антон ПолухинC++ CoreHard Autumn 2018. Полезный constexpr - Антон Полухин
C++ CoreHard Autumn 2018. Полезный constexpr - Антон Полухинcorehard_by
 
C++ CoreHard Autumn 2018. Text Formatting For a Future Range-Based Standard L...
C++ CoreHard Autumn 2018. Text Formatting For a Future Range-Based Standard L...C++ CoreHard Autumn 2018. Text Formatting For a Future Range-Based Standard L...
C++ CoreHard Autumn 2018. Text Formatting For a Future Range-Based Standard L...corehard_by
 
Исключительная модель памяти. Алексей Ткаченко ➠ CoreHard Autumn 2019
Исключительная модель памяти. Алексей Ткаченко ➠ CoreHard Autumn 2019Исключительная модель памяти. Алексей Ткаченко ➠ CoreHard Autumn 2019
Исключительная модель памяти. Алексей Ткаченко ➠ CoreHard Autumn 2019corehard_by
 
Как помочь и как помешать компилятору. Андрей Олейников ➠ CoreHard Autumn 2019
Как помочь и как помешать компилятору. Андрей Олейников ➠  CoreHard Autumn 2019Как помочь и как помешать компилятору. Андрей Олейников ➠  CoreHard Autumn 2019
Как помочь и как помешать компилятору. Андрей Олейников ➠ CoreHard Autumn 2019corehard_by
 
Автоматизируй это. Кирилл Тихонов ➠ CoreHard Autumn 2019
Автоматизируй это. Кирилл Тихонов ➠  CoreHard Autumn 2019Автоматизируй это. Кирилл Тихонов ➠  CoreHard Autumn 2019
Автоматизируй это. Кирилл Тихонов ➠ CoreHard Autumn 2019corehard_by
 

More from corehard_by (20)

C++ CoreHard Autumn 2018. Создание пакетов для открытых библиотек через conan...
C++ CoreHard Autumn 2018. Создание пакетов для открытых библиотек через conan...C++ CoreHard Autumn 2018. Создание пакетов для открытых библиотек через conan...
C++ CoreHard Autumn 2018. Создание пакетов для открытых библиотек через conan...
 
C++ CoreHard Autumn 2018. Что должен знать каждый C++ программист или Как про...
C++ CoreHard Autumn 2018. Что должен знать каждый C++ программист или Как про...C++ CoreHard Autumn 2018. Что должен знать каждый C++ программист или Как про...
C++ CoreHard Autumn 2018. Что должен знать каждый C++ программист или Как про...
 
C++ CoreHard Autumn 2018. Actors vs CSP vs Tasks vs ... - Евгений Охотников
C++ CoreHard Autumn 2018. Actors vs CSP vs Tasks vs ... - Евгений ОхотниковC++ CoreHard Autumn 2018. Actors vs CSP vs Tasks vs ... - Евгений Охотников
C++ CoreHard Autumn 2018. Actors vs CSP vs Tasks vs ... - Евгений Охотников
 
C++ CoreHard Autumn 2018. Знай свое "железо": иерархия памяти - Александр Титов
C++ CoreHard Autumn 2018. Знай свое "железо": иерархия памяти - Александр ТитовC++ CoreHard Autumn 2018. Знай свое "железо": иерархия памяти - Александр Титов
C++ CoreHard Autumn 2018. Знай свое "железо": иерархия памяти - Александр Титов
 
C++ CoreHard Autumn 2018. Информационная безопасность и разработка ПО - Евген...
C++ CoreHard Autumn 2018. Информационная безопасность и разработка ПО - Евген...C++ CoreHard Autumn 2018. Информационная безопасность и разработка ПО - Евген...
C++ CoreHard Autumn 2018. Информационная безопасность и разработка ПО - Евген...
 
C++ CoreHard Autumn 2018. Заглядываем под капот «Поясов по C++» - Илья Шишков
C++ CoreHard Autumn 2018. Заглядываем под капот «Поясов по C++» - Илья ШишковC++ CoreHard Autumn 2018. Заглядываем под капот «Поясов по C++» - Илья Шишков
C++ CoreHard Autumn 2018. Заглядываем под капот «Поясов по C++» - Илья Шишков
 
C++ CoreHard Autumn 2018. Ускорение сборки C++ проектов, способы и последстви...
C++ CoreHard Autumn 2018. Ускорение сборки C++ проектов, способы и последстви...C++ CoreHard Autumn 2018. Ускорение сборки C++ проектов, способы и последстви...
C++ CoreHard Autumn 2018. Ускорение сборки C++ проектов, способы и последстви...
 
C++ CoreHard Autumn 2018. Метаклассы: воплощаем мечты в реальность - Сергей С...
C++ CoreHard Autumn 2018. Метаклассы: воплощаем мечты в реальность - Сергей С...C++ CoreHard Autumn 2018. Метаклассы: воплощаем мечты в реальность - Сергей С...
C++ CoreHard Autumn 2018. Метаклассы: воплощаем мечты в реальность - Сергей С...
 
C++ CoreHard Autumn 2018. Что не умеет оптимизировать компилятор - Александр ...
C++ CoreHard Autumn 2018. Что не умеет оптимизировать компилятор - Александр ...C++ CoreHard Autumn 2018. Что не умеет оптимизировать компилятор - Александр ...
C++ CoreHard Autumn 2018. Что не умеет оптимизировать компилятор - Александр ...
 
C++ CoreHard Autumn 2018. Кодогенерация C++ кроссплатформенно. Продолжение - ...
C++ CoreHard Autumn 2018. Кодогенерация C++ кроссплатформенно. Продолжение - ...C++ CoreHard Autumn 2018. Кодогенерация C++ кроссплатформенно. Продолжение - ...
C++ CoreHard Autumn 2018. Кодогенерация C++ кроссплатформенно. Продолжение - ...
 
C++ CoreHard Autumn 2018. Concurrency and Parallelism in C++17 and C++20/23 -...
C++ CoreHard Autumn 2018. Concurrency and Parallelism in C++17 and C++20/23 -...C++ CoreHard Autumn 2018. Concurrency and Parallelism in C++17 and C++20/23 -...
C++ CoreHard Autumn 2018. Concurrency and Parallelism in C++17 and C++20/23 -...
 
C++ CoreHard Autumn 2018. Обработка списков на C++ в функциональном стиле - В...
C++ CoreHard Autumn 2018. Обработка списков на C++ в функциональном стиле - В...C++ CoreHard Autumn 2018. Обработка списков на C++ в функциональном стиле - В...
C++ CoreHard Autumn 2018. Обработка списков на C++ в функциональном стиле - В...
 
C++ Corehard Autumn 2018. Обучаем на Python, применяем на C++ - Павел Филонов
C++ Corehard Autumn 2018. Обучаем на Python, применяем на C++ - Павел ФилоновC++ Corehard Autumn 2018. Обучаем на Python, применяем на C++ - Павел Филонов
C++ Corehard Autumn 2018. Обучаем на Python, применяем на C++ - Павел Филонов
 
C++ CoreHard Autumn 2018. Asynchronous programming with ranges - Ivan Čukić
C++ CoreHard Autumn 2018. Asynchronous programming with ranges - Ivan ČukićC++ CoreHard Autumn 2018. Asynchronous programming with ranges - Ivan Čukić
C++ CoreHard Autumn 2018. Asynchronous programming with ranges - Ivan Čukić
 
C++ CoreHard Autumn 2018. Debug C++ Without Running - Anastasia Kazakova
C++ CoreHard Autumn 2018. Debug C++ Without Running - Anastasia KazakovaC++ CoreHard Autumn 2018. Debug C++ Without Running - Anastasia Kazakova
C++ CoreHard Autumn 2018. Debug C++ Without Running - Anastasia Kazakova
 
C++ CoreHard Autumn 2018. Полезный constexpr - Антон Полухин
C++ CoreHard Autumn 2018. Полезный constexpr - Антон ПолухинC++ CoreHard Autumn 2018. Полезный constexpr - Антон Полухин
C++ CoreHard Autumn 2018. Полезный constexpr - Антон Полухин
 
C++ CoreHard Autumn 2018. Text Formatting For a Future Range-Based Standard L...
C++ CoreHard Autumn 2018. Text Formatting For a Future Range-Based Standard L...C++ CoreHard Autumn 2018. Text Formatting For a Future Range-Based Standard L...
C++ CoreHard Autumn 2018. Text Formatting For a Future Range-Based Standard L...
 
Исключительная модель памяти. Алексей Ткаченко ➠ CoreHard Autumn 2019
Исключительная модель памяти. Алексей Ткаченко ➠ CoreHard Autumn 2019Исключительная модель памяти. Алексей Ткаченко ➠ CoreHard Autumn 2019
Исключительная модель памяти. Алексей Ткаченко ➠ CoreHard Autumn 2019
 
Как помочь и как помешать компилятору. Андрей Олейников ➠ CoreHard Autumn 2019
Как помочь и как помешать компилятору. Андрей Олейников ➠  CoreHard Autumn 2019Как помочь и как помешать компилятору. Андрей Олейников ➠  CoreHard Autumn 2019
Как помочь и как помешать компилятору. Андрей Олейников ➠ CoreHard Autumn 2019
 
Автоматизируй это. Кирилл Тихонов ➠ CoreHard Autumn 2019
Автоматизируй это. Кирилл Тихонов ➠  CoreHard Autumn 2019Автоматизируй это. Кирилл Тихонов ➠  CoreHard Autumn 2019
Автоматизируй это. Кирилл Тихонов ➠ CoreHard Autumn 2019
 

Recently uploaded

Artificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxArtificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxhariprasad279825
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 3652toLead Limited
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .Alan Dix
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebUiPathCommunity
 
Sample pptx for embedding into website for demo
Sample pptx for embedding into website for demoSample pptx for embedding into website for demo
Sample pptx for embedding into website for demoHarshalMandlekar2
 
What is Artificial Intelligence?????????
What is Artificial Intelligence?????????What is Artificial Intelligence?????????
What is Artificial Intelligence?????????blackmambaettijean
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxLoriGlavin3
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024Stephanie Beckett
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii SoldatenkoFwdays
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek SchlawackFwdays
 
Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersRaghuram Pandurangan
 
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxPasskey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxLoriGlavin3
 
Training state-of-the-art general text embedding
Training state-of-the-art general text embeddingTraining state-of-the-art general text embedding
Training state-of-the-art general text embeddingZilliz
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr BaganFwdays
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxLoriGlavin3
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Mark Simos
 
Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rick Flair
 

Recently uploaded (20)

Artificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxArtificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptx
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio Web
 
Sample pptx for embedding into website for demo
Sample pptx for embedding into website for demoSample pptx for embedding into website for demo
Sample pptx for embedding into website for demo
 
What is Artificial Intelligence?????????
What is Artificial Intelligence?????????What is Artificial Intelligence?????????
What is Artificial Intelligence?????????
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
 
Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information Developers
 
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxPasskey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
 
Training state-of-the-art general text embedding
Training state-of-the-art general text embeddingTraining state-of-the-art general text embedding
Training state-of-the-art general text embedding
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptx
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
 
Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...
 

Многогранный С++ на практике

  • 1. Versatile C++ Mikhail Matrosov, Expert Software Engineer, Align Technology
  • 2. x y Mikhail Matrosov, Versatile C++, CoreHard 2018 2
  • 3. x y Mikhail Matrosov, Versatile C++, CoreHard 2018 3
  • 4. Mikhail Matrosov, Versatile C++, CoreHard 2018 4
  • 5. 0 1 2 3 4 5 6 1 2 3 4 0 1 2 3 4 5 6 0 1 2 3 4 5 6 4 5 6 0 1 Mikhail Matrosov, Versatile C++, CoreHard 2018 5
  • 9. [ ) [ )[ [ ) [ ) [ ) [ ) [) ) 1) 2) 3) 4) 5) 6) 7) 8) Mikhail Matrosov, Versatile C++, CoreHard 2018 9
  • 10. [ ) [ ) [[ [ ) [ [ ) [ ) [ [ )[ [)[ [ )[ [ 1) 2) 3) 4) 5) 6) 7) 8) Mikhail Matrosov, Versatile C++, CoreHard 2018 10
  • 11. [ ) [ ) [[ [ ) [ [ ) [ ) [ ) [ )[) [)[) [) )[) ) [) ) 1) 2) 3) 4) 5) 6) 7) 8) Mikhail Matrosov, Versatile C++, CoreHard 2018 11
  • 12. struct Point { int x; int y; }; bool isPositive(const Point& pt) { return pt.x >= 0; }; Mikhail Matrosov, Versatile C++, CoreHard 2018 12
  • 13. std::vector<Point> extract(const std::vector<Point>& points) { Mikhail Matrosov, Versatile C++, CoreHard 2018 13
  • 14. std::vector<Point> extract(const std::vector<Point>& points) { auto begin1 = std::find_if (points.begin(), points.end(), isPositive); [ Mikhail Matrosov, Versatile C++, CoreHard 2018 14
  • 15. std::vector<Point> extract(const std::vector<Point>& points) { auto begin1 = std::find_if (points.begin(), points.end(), isPositive); auto end1 = std::find_if_not(begin1, points.end(), isPositive); [ ) Mikhail Matrosov, Versatile C++, CoreHard 2018 15
  • 16. std::vector<Point> extract(const std::vector<Point>& points) { auto begin1 = std::find_if (points.begin(), points.end(), isPositive); auto end1 = std::find_if_not(begin1, points.end(), isPositive); auto begin2 = std::find_if (end1, points.end(), isPositive); [ ) [ Mikhail Matrosov, Versatile C++, CoreHard 2018 16
  • 17. std::vector<Point> extract(const std::vector<Point>& points) { auto begin1 = std::find_if (points.begin(), points.end(), isPositive); auto end1 = std::find_if_not(begin1, points.end(), isPositive); auto begin2 = std::find_if (end1, points.end(), isPositive); auto end2 = std::find_if_not(begin2, points.end(), isPositive); [ ) [ ) Mikhail Matrosov, Versatile C++, CoreHard 2018 17
  • 18. std::vector<Point> extract(const std::vector<Point>& points) { auto begin1 = std::find_if (points.begin(), points.end(), isPositive); auto end1 = std::find_if_not(begin1, points.end(), isPositive); auto begin2 = std::find_if (end1, points.end(), isPositive); auto end2 = std::find_if_not(begin2, points.end(), isPositive); if (!(begin2 == end2 || begin1 == points.begin() && end2 == points.end())) throw std::runtime_error("Unexpected order"); [ ) [ ) Mikhail Matrosov, Versatile C++, CoreHard 2018 18
  • 19. std::vector<Point> extract(const std::vector<Point>& points) { auto begin1 = std::find_if (points.begin(), points.end(), isPositive); auto end1 = std::find_if_not(begin1, points.end(), isPositive); auto begin2 = std::find_if (end1, points.end(), isPositive); auto end2 = std::find_if_not(begin2, points.end(), isPositive); if (!(begin2 == end2 || begin1 == points.begin() && end2 == points.end())) throw std::runtime_error("Unexpected order"); std::vector<Point> result; result.reserve((end1 - begin1) + (end2 - begin2)); [ ) [ ) Mikhail Matrosov, Versatile C++, CoreHard 2018 19
  • 20. std::vector<Point> extract(const std::vector<Point>& points) { auto begin1 = std::find_if (points.begin(), points.end(), isPositive); auto end1 = std::find_if_not(begin1, points.end(), isPositive); auto begin2 = std::find_if (end1, points.end(), isPositive); auto end2 = std::find_if_not(begin2, points.end(), isPositive); if (!(begin2 == end2 || begin1 == points.begin() && end2 == points.end())) throw std::runtime_error("Unexpected order"); std::vector<Point> result; result.reserve((end1 - begin1) + (end2 - begin2)); result.insert(result.end(), begin2, end2); result.insert(result.end(), begin1, end1); [ ) [ ) Mikhail Matrosov, Versatile C++, CoreHard 2018 20
  • 21. std::vector<Point> extract(const std::vector<Point>& points) { auto begin1 = std::find_if (points.begin(), points.end(), isPositive); auto end1 = std::find_if_not(begin1, points.end(), isPositive); auto begin2 = std::find_if (end1, points.end(), isPositive); auto end2 = std::find_if_not(begin2, points.end(), isPositive); if (!(begin2 == end2 || begin1 == points.begin() && end2 == points.end())) throw std::runtime_error("Unexpected order"); std::vector<Point> result; result.reserve((end1 - begin1) + (end2 - begin2)); result.insert(result.end(), begin2, end2); result.insert(result.end(), begin1, end1); return result; } [ ) [ ) Mikhail Matrosov, Versatile C++, CoreHard 2018 21
  • 22. Mikhail Matrosov, Versatile C++, CoreHard 2018 22
  • 23. std::vector<Point> extract(std::vector<Point>&& points) { Mikhail Matrosov, Versatile C++, CoreHard 2018 23
  • 24. std::vector<Point> extract(std::vector<Point>&& points) { auto begin1 = std::find_if (points.begin(), points.end(), isPositive); auto end1 = std::find_if_not(begin1, points.end(), isPositive); auto begin2 = std::find_if (end1, points.end(), isPositive); auto end2 = std::find_if_not(begin2, points.end(), isPositive); if (!(begin2 == end2 || begin1 == points.begin() && end2 == points.end())) throw std::runtime_error("Unexpected order"); Mikhail Matrosov, Versatile C++, CoreHard 2018 24
  • 25. std::vector<Point> extract(std::vector<Point>&& points) { auto begin1 = std::find_if (points.begin(), points.end(), isPositive); auto end1 = std::find_if_not(begin1, points.end(), isPositive); auto begin2 = std::find_if (end1, points.end(), isPositive); auto end2 = std::find_if_not(begin2, points.end(), isPositive); if (!(begin2 == end2 || begin1 == points.begin() && end2 == points.end())) throw std::runtime_error("Unexpected order"); gather(points.begin(), points.end(), begin1, end1, begin2, end2); 0 1 2 3 4 5 6 7 0 1 25 6 7 ? ? gather 0 1 2 3 4 5 6 7 4 5 ?2 3 ? ? gather ? Mikhail Matrosov, Versatile C++, CoreHard 2018 25
  • 26. std::vector<Point> extract(std::vector<Point>&& points) { auto begin1 = std::find_if (points.begin(), points.end(), isPositive); auto end1 = std::find_if_not(begin1, points.end(), isPositive); auto begin2 = std::find_if (end1, points.end(), isPositive); auto end2 = std::find_if_not(begin2, points.end(), isPositive); if (!(begin2 == end2 || begin1 == points.begin() && end2 == points.end())) throw std::runtime_error("Unexpected order"); gather(points.begin(), points.end(), begin1, end1, begin2, end2); points.resize((end1 - begin1) + (end2 - begin2)); Mikhail Matrosov, Versatile C++, CoreHard 2018 26
  • 27. std::vector<Point> extract(std::vector<Point>&& points) { auto begin1 = std::find_if (points.begin(), points.end(), isPositive); auto end1 = std::find_if_not(begin1, points.end(), isPositive); auto begin2 = std::find_if (end1, points.end(), isPositive); auto end2 = std::find_if_not(begin2, points.end(), isPositive); if (!(begin2 == end2 || begin1 == points.begin() && end2 == points.end())) throw std::runtime_error("Unexpected order"); gather(points.begin(), points.end(), begin1, end1, begin2, end2); points.resize((end1 - begin1) + (end2 - begin2)); return std::move(points); } Mikhail Matrosov, Versatile C++, CoreHard 2018 27
  • 28. Mikhail Matrosov, Versatile C++, CoreHard 2018 28 Never apply std::move after return… Always apply std::move on r-value references! c++11 Return value optimization or move?
  • 29. template<class It> void gather(It first, It last, It begin1, It end1, It begin2, It end2) { assert(begin2 == end2 || begin1 == first && end2 == last); Mikhail Matrosov, Versatile C++, CoreHard 2018 29 0 1 2 3 4 5 6 7 0 1 25 6 7 ? ? gather 0 1 2 3 4 5 6 7 4 5 ?2 3 ? ? gather ?
  • 30. first end2begin2 last end1begin1 middlefirst end2 begin2 last end1 middle begin1 template<class It> void gather(It first, It last, It begin1, It end1, It begin2, It end2) { assert(begin2 == end2 || begin1 == first && end2 == last); auto middle = begin2 == end2 ? begin1 : begin2; std::rotate(first, middle, last); } 0 1 2 3 4 5 6 70 1 2 3 4 5 6 7 Mikhail Matrosov, Versatile C++, CoreHard 2018 30
  • 31. 220≈1M 1/4 1/41/2 31Mikhail Matrosov, Versatile C++, CoreHard 2018
  • 32. Mikhail Matrosov, Versatile C++, CoreHard 2018 32
  • 33. /usr/bin/clang++ -- broken cmake ../ sudo update-alternatives --list clang /usr/bin/clang++-6.0 -stdlib=libc++ -v Selected GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/7.3.0 Candidate multilib: .;@m64 Selected multilib: .;@m64 clang -cc1 version 6.0.0 based upon LLVM 6.0.0 default target x86_64-pc-linux-gnu ignoring nonexistent directory "/include" ignoring duplicate directory "/usr/include/clang/6.0.0/include" #include "..." search starts here: #include <...> search starts here: /usr/include/c++/v1 /usr/include/clang/6.0.0/include /usr/local/include /usr/include/x86_64-linux-gnu /usr/include End of search list. ../../clang_test/hello.cpp:2:10: fatal error: 'experimental/generator' file not found #include <experimental/generator> ^~~~~~~~~~~~~~~~~~~~~~~~ 1 error generated.
  • 34. # of segments? At the beginning? Enough room? Nothing to do! Fall back to rotate() Move to front! Move both! One Two Yes No Yes No Mikhail Matrosov, Versatile C++, CoreHard 2018 34
  • 35. template<class It> void gather(It first, It last, It begin1, It end1, It begin2, It end2) { assert(begin2 == end2 || begin1 == first && end2 == last); if (begin2 == end2) { if (begin1 != first) std::move(begin1, end1, first); // Like std::copy(), but moves elements return; } auto len2 = std::distance(begin2, end2); // Better for generic code auto lenFree = std::distance(end1, begin2); if (len2 <= lenFree) { auto len1 = std::distance(begin1, end1); std::move_backward(begin1, end1, first + len1 + len2); std::move(begin2, end2, first); return; } std::rotate(first, begin2, last); } 0 1 2 3 4 35
  • 36. Mikhail Matrosov, Versatile C++, CoreHard 2018 36
  • 37. Mikhail Matrosov, Versatile C++, CoreHard 2018 37
  • 38. std::list<Point> extract(std::list<Point>&& points) { Mikhail Matrosov, Versatile C++, CoreHard 2018 38
  • 39. std::list<Point> extract(std::list<Point>&& points) { auto begin1 = std::find_if (points.begin(), points.end(), isPositive); auto end1 = std::find_if_not(begin1, points.end(), isPositive); auto begin2 = std::find_if (end1, points.end(), isPositive); auto end2 = std::find_if_not(begin2, points.end(), isPositive); if (!(begin2 == end2 || begin1 == points.begin() && end2 == points.end())) throw std::runtime_error("Unexpected order"); Mikhail Matrosov, Versatile C++, CoreHard 2018 39
  • 40. std::list<Point> extract(std::list<Point>&& points) { auto begin1 = std::find_if (points.begin(), points.end(), isPositive); auto end1 = std::find_if_not(begin1, points.end(), isPositive); auto begin2 = std::find_if (end1, points.end(), isPositive); auto end2 = std::find_if_not(begin2, points.end(), isPositive); if (!(begin2 == end2 || begin1 == points.begin() && end2 == points.end())) throw std::runtime_error("Unexpected order"); points.erase(points.begin(), begin1); points.splice(points.begin(), points, begin2, end2); points.erase(end1, points.end()); return std::move(points); } Mikhail Matrosov, Versatile C++, CoreHard 2018 40
  • 41. points.erase(points.begin(), begin1); points.splice(points.begin(), points, begin2, end2); points.erase(end1, points.end()); 2 3 4 5 6 7 0 1 2 3 4 5 6 7 list 0 1 list Mikhail Matrosov, Versatile C++, CoreHard 2018 41
  • 42. Mikhail Matrosov, Versatile C++, CoreHard 2018 42
  • 43. YOU WERE THE CHOSEN ONE! std::list 43
  • 44. auto extract(const std::vector<Point>& points) { auto begin1 = std::find_if (points.begin(), points.end(), isPositive); auto end1 = std::find_if_not(begin1, points.end(), isPositive); auto begin2 = std::find_if (end1, points.end(), isPositive); auto end2 = std::find_if_not(begin2, points.end(), isPositive); if (!(begin2 == end2 || begin1 == points.begin() && end2 == points.end())) throw std::runtime_error("Unexpected order"); Mikhail Matrosov, Versatile C++, CoreHard 2018 44
  • 45. auto extract(const std::vector<Point>& points) { auto begin1 = std::find_if (points.begin(), points.end(), isPositive); auto end1 = std::find_if_not(begin1, points.end(), isPositive); auto begin2 = std::find_if (end1, points.end(), isPositive); auto end2 = std::find_if_not(begin2, points.end(), isPositive); if (!(begin2 == end2 || begin1 == points.begin() && end2 == points.end())) throw std::runtime_error("Unexpected order"); return boost::join(boost::make_iterator_range(begin2, end2), boost::make_iterator_range(begin1, end1)); } Mikhail Matrosov, Versatile C++, CoreHard 2018 45
  • 46. 46Mikhail Matrosov, Versatile C++, CoreHard 2018
  • 47. 47 template<class It> class WrappingIterator : public boost::iterator_facade<WrappingIterator<It>, typename It::value_type, boost::random_access_traversal_tag, typename It::reference> { public: WrappingIterator() = default; WrappingIterator(It it, It begin, It end) : m_begin(begin), m_size(end - begin), m_offset(it - begin) {} template <class OtherIt> WrappingIterator(const WrappingIterator<OtherIt>& other) : m_begin(other.m_begin), m_size(other.m_size), m_offset(other.m_offset) {} private: friend class boost::iterator_core_access; template<class> friend class WrappingIterator; using Base = boost::iterator_facade<WrappingIterator<It>, typename It::value_type, boost::random_access_traversal_tag, typename It::reference>; // Core interface functions (on the next slide) It m_begin; size_t m_size; size_t m_offset; };
  • 48. 48 typename Base::reference dereference() const { return *(m_begin + (m_offset < m_size ? m_offset : m_offset - m_size)); } template <class OtherIt> bool equal(const WrappingIterator<OtherIt>& other) const { assert(other.m_begin == m_begin && other.m_size == m_size); return other.m_offset == m_offset; } void advance(typename Base::difference_type n) { m_offset += n; } void increment() { ++m_offset; } void decrement() { --m_offset; } template <class OtherIt> typename Base::difference_type distance_to(const WrappingIterator<OtherIt>& other) const { assert(other.m_begin == m_begin && other.m_size == m_size); return other.m_offset - m_offset; }
  • 49. 49Mikhail Matrosov, Versatile C++, CoreHard 2018
  • 50. auto extract(const std::vector<Point>& points) { auto begin1 = std::find_if (points.begin(), points.end(), isPositive); auto end1 = std::find_if_not(begin1, points.end(), isPositive); auto begin2 = std::find_if (end1, points.end(), isPositive); auto end2 = std::find_if_not(begin2, points.end(), isPositive); if (!(begin2 == end2 || begin1 == points.begin() && end2 == points.end())) throw std::runtime_error("Unexpected order"); return boost::join(boost::make_iterator_range(begin2, end2), boost::make_iterator_range(begin1, end1)); } Mikhail Matrosov, Versatile C++, CoreHard 2018 50
  • 51. template<class It> auto extract(const std::vector<Point>& points) { auto begin1 = std::find_if (points.begin(), points.end(), isPositive); auto end1 = std::find_if_not(begin1, points.end(), isPositive); auto begin2 = std::find_if (end1, points.end(), isPositive); auto end2 = std::find_if_not(begin2, points.end(), isPositive); if (!(begin2 == end2 || begin1 == points.begin() && end2 == points.end())) throw std::runtime_error("Unexpected order"); return boost::join(boost::make_iterator_range(begin2, end2), boost::make_iterator_range(begin1, end1)); } Mikhail Matrosov, Versatile C++, CoreHard 2018 51
  • 52. template<class It> auto extract(It first, It last) { auto begin1 = std::find_if (points.begin(), points.end(), isPositive); auto end1 = std::find_if_not(begin1, points.end(), isPositive); auto begin2 = std::find_if (end1, points.end(), isPositive); auto end2 = std::find_if_not(begin2, points.end(), isPositive); if (!(begin2 == end2 || begin1 == points.begin() && end2 == points.end())) throw std::runtime_error("Unexpected order"); return boost::join(boost::make_iterator_range(begin2, end2), boost::make_iterator_range(begin1, end1)); } Mikhail Matrosov, Versatile C++, CoreHard 2018 52
  • 53. template<class It> auto extract(It first, It last) { auto begin1 = std::find_if (first, last, isPositive); auto end1 = std::find_if_not(begin1, last, isPositive); auto begin2 = std::find_if (end1, last, isPositive); auto end2 = std::find_if_not(begin2, last, isPositive); if (!(begin2 == end2 || begin1 == first && end2 == last)) throw std::runtime_error("Unexpected order"); return boost::join(boost::make_iterator_range(begin2, end2), boost::make_iterator_range(begin1, end1)); } Mikhail Matrosov, Versatile C++, CoreHard 2018 53
  • 54. template<class It> auto extract(It first, It last) { It begin1 = std::find_if (first, last, isPositive); It end1 = std::find_if_not(begin1, last, isPositive); It begin2 = std::find_if (end1, last, isPositive); It end2 = std::find_if_not(begin2, last, isPositive); if (!(begin2 == end2 || begin1 == first && end2 == last)) throw std::runtime_error("Unexpected order"); return boost::join(boost::make_iterator_range(begin2, end2), boost::make_iterator_range(begin1, end1)); } Mikhail Matrosov, Versatile C++, CoreHard 2018 54
  • 55. template<class It, class Predicate> auto extract(It first, It last, Predicate p) { It begin1 = std::find_if (first, last, p); It end1 = std::find_if_not(begin1, last, p); It begin2 = std::find_if (end1, last, p); It end2 = std::find_if_not(begin2, last, p); if (!(begin2 == end2 || begin1 == first && end2 == last)) throw std::runtime_error("Unexpected order"); return boost::join(boost::make_iterator_range(begin2, end2), boost::make_iterator_range(begin1, end1)); } Mikhail Matrosov, Versatile C++, CoreHard 2018 55
  • 56. template<class It, class Predicate> auto extract(It first, It last, Predicate p) { It begin1 = std::find_if (first, last, p); It end1 = std::find_if_not(begin1, last, p); It begin2 = std::find_if (end1, last, p); It end2 = std::find_if_not(begin2, last, p); if (!(begin2 == end2 || begin1 == first && end2 == last)) throw std::runtime_error("Unexpected order"); return boost::join(boost::make_iterator_range(begin2, end2), boost::make_iterator_range(begin1, end1)); } Mikhail Matrosov, Versatile C++, CoreHard 2018 56
  • 57. 57Mikhail Matrosov, Versatile C++, CoreHard 2018
  • 58. template<class It, class Predicate> auto extract(It first, It last, Predicate p) { It begin1 = std::find_if (first, last, p); It end1 = std::find_if_not(begin1, last, p); It begin2 = std::find_if (end1, last, p); It end2 = std::find_if_not(begin2, last, p); if (!(begin2 == end2 || begin1 == first && end2 == last)) throw std::runtime_error("Unexpected order"); return boost::join(boost::make_iterator_range(begin2, end2), boost::make_iterator_range(begin1, end1)); } Mikhail Matrosov, Versatile C++, CoreHard 2018 58
  • 59. template<class It, class Predicate> auto extract(It first, It last, Predicate p) { It begin1 = std::find_if (first, last, p); It end1 = std::find_if_not(begin1, last, p); It begin2 = std::find_if (end1, last, p); It end2 = std::find_if_not(begin2, last, p); if (!(begin2 == end2 || begin1 == first && end2 == last)) throw std::runtime_error("Unexpected order"); return ranges::view::concat(ranges::range<It>(begin2, end2), ranges::range<It>(begin1, end1)); } Mikhail Matrosov, Versatile C++, CoreHard 2018 59
  • 60. 60Mikhail Matrosov, Versatile C++, CoreHard 2018
  • 61. #include <experimental/generator> namespace std { using std::experimental::generator; } // For VC++ compile with /await Coroutines! 61Mikhail Matrosov, Versatile C++, CoreHard 2018
  • 62. // Not a generic function, since compilers at the moment // may have troubles with template coroutines std::generator<Point> extract(const std::vector<Point>& points) { auto begin1 = std::find_if (points.begin(), points.end(), isPositive); auto end1 = std::find_if_not(begin1, points.end(), isPositive); auto begin2 = std::find_if (end1, points.end(), isPositive); auto end2 = std::find_if_not(begin2, points.end(), isPositive); if (!(begin2 == end2 || begin1 == points.begin() && end2 == points.end())) throw std::runtime_error("Unexpected order"); for (auto it = begin2; it != end2; ++it) co_yield *it; for (auto it = begin1; it != end1; ++it) co_yield *it; } // Used just as ranges: // std::generator provides begin() and end() methods returning input iterators Mikhail Matrosov, Versatile C++, CoreHard 2018 62
  • 63. 63Mikhail Matrosov, Versatile C++, CoreHard 2018
  • 64. “C++ Coroutines - a negative overhead abstraction” 64
  • 65. Mikhail Matrosov, Versatile C++, CoreHard 2018 65
  • 66. template<class It, class Predicate> auto extract(It first, It last, Predicate p) { It begin1 = std::find_if (first, last, p); It end1 = std::find_if_not(begin1, last, p); It begin2 = std::find_if (end1, last, p); It end2 = std::find_if_not(begin2, last, p); if (!(begin2 == end2 || begin1 == first && end2 == last)) throw std::runtime_error("Unexpected order"); return boost::join(boost::make_iterator_range(begin2, end2), boost::make_iterator_range(begin1, end1)); } Mikhail Matrosov, Versatile C++, CoreHard 2018 66
  • 67. template<class It, class Predicate> auto extract(It first, It last, Predicate p) { It begin1 = std::find_if (first, last, p); It end1 = std::find_if_not(begin1, last, p); It begin2 = std::find_if (end1, last, p); It end2 = last; if (!(begin2 == end2 || begin1 == first && end2 == last)) throw std::runtime_error("Unexpected order"); return boost::join(boost::make_iterator_range(begin2, end2), boost::make_iterator_range(begin1, end1)); } Mikhail Matrosov, Versatile C++, CoreHard 2018 67
  • 68. template<class It, class Predicate> auto extract(It first, It last, Predicate p) { It begin1 = std::find_if (first, last, p); It end1 = std::find_if_not(begin1, last, p); It begin2 = std::find_if (end1, last, p); It end2 = last; assert(end2 == std::find_if_not(begin2, last, p) && (begin2 == end2 || begin1 == first && end2 == last)); return boost::join(boost::make_iterator_range(begin2, end2), boost::make_iterator_range(begin1, end1)); } Mikhail Matrosov, Versatile C++, CoreHard 2018 68
  • 69. 69Mikhail Matrosov, Versatile C++, CoreHard 2018
  • 70. template<class It, class Predicate> auto extract(It first, It last, Predicate p) { It begin1 = std::find_if (first, last, p); It end1 = std::find_if_not(begin1, last, p); It begin2 = std::find_if (end1, last, p); It end2 = last; assert(end2 == std::find_if_not(begin2, last, p) && (begin2 == end2 || begin1 == first && end2 == last)); return boost::join(boost::make_iterator_range(begin2, end2), boost::make_iterator_range(begin1, end1)); } 70
  • 71. template<class It> struct Bounds { It begin1, end1, begin2, end2; }; template<class It, class Predicate> Bounds<It> findBounds(It first, It last, Predicate p) { It begin1 = std::find_if (first, last, p); It end1 = std::find_if_not(begin1, last, p); It begin2 = std::find_if (end1, last, p); return { begin1, end1, begin2, last }; } template<class It, class Predicate> auto extract(It first, It last, Predicate p) { auto bounds = findBounds(first, last, p); return boost::join(boost::make_iterator_range(bounds.begin2, bounds.end2), boost::make_iterator_range(bounds.begin1, bounds.end1)); } 71
  • 72. 72Mikhail Matrosov, Versatile C++, CoreHard 2018
  • 73. All negative All positive All negativeAll positive 73Mikhail Matrosov, Versatile C++, CoreHard 2018
  • 74. 74Mikhail Matrosov, Versatile C++, CoreHard 2018
  • 75. All positive All negative All positiveAll negative 75Mikhail Matrosov, Versatile C++, CoreHard 2018
  • 76. template<class It, class Predicate> Bounds<It> findBounds(It first, It last, Predicate p) { Bounds<It> bounds = { first, last, last, last }; // Whole sequence by default if (first == last) return bounds; if (!p(*first) || !p(last[-1])) { // One segment, or empty It sample = findAny(first, last, p); bounds.begin1 = std::partition_point(first, sample, std::not_fn(p)); bounds.end1 = std::partition_point(sample, last, p); } else if (It hole = findAny(first, last, std::not_fn(p)); hole != last) { // Two segments bounds.end1 = std::partition_point(first, hole, p); bounds.begin2 = std::partition_point(hole, last, std::not_fn(p)); } return bounds; } 76
  • 77. 10 32 54 76 98 1110 8 4 9 2 10 5 11 1 6 12 7 3 Take element in the middle, then recurse to left and right 77Mikhail Matrosov, Versatile C++, CoreHard 2018
  • 78. 10 32 54 76 98 1110 8 4 9 2 10 5 11 1 6 12 7 3 Take element in the middle, then recurse to left and right 78 Level First index Distances to next 1 6 2 3 6 3 1 4, 3, 3 4 0 2, 2, 3, 3 Mikhail Matrosov, Versatile C++, CoreHard 2018
  • 79. 10 32 54 76 98 1110 1312 14 8 4 9 2 10 5 11 1 12 6 13 3 14 7 15 Take element in the middle, then recurse to left and right 79Mikhail Matrosov, Versatile C++, CoreHard 2018
  • 80. 10 32 54 76 98 1110 1312 14 8 4 9 2 10 5 11 1 12 6 13 3 14 7 15 Level First index Distances to next 1 7 2 3 8 3 1 4, 4, 4 4 0 2, 2, 2, 2, 2, 2, 2 Take element in the middle, then recurse to left and right 80Mikhail Matrosov, Versatile C++, CoreHard 2018
  • 81. 10 32 54 76 98 1110 7 4 8 2 9 5 10 1 11 6 12 3 Repeat as if it was for the power of two 81Mikhail Matrosov, Versatile C++, CoreHard 2018
  • 82. 10 32 54 76 98 1110 7 4 8 2 9 5 10 1 11 6 12 3 Level First index Distances to next 1 7 2 3 8 3 1 4, 4 4 0 2, 2, 2, 2, 2 82Mikhail Matrosov, Versatile C++, CoreHard 2018 Repeat as if it was for the power of two
  • 83. template<class It, class Predicate> // It is RandomAccess It findAny(It first, It last, Predicate p) { using diff_t = typename std::iterator_traits<It>::difference_type; diff_t n = last - first; diff_t step = 1; while (step <= n) step *= 2; while (step > 1) { for (diff_t i = step / 2 - 1; i < n; i += step) if (p(first[i])) return first + i; step /= 2; } return last; } 83
  • 84. 84Mikhail Matrosov, Versatile C++, CoreHard 2018
  • 85. template<class It, class Predicate> Bounds<It> findBounds(It first, It last, Predicate p, std::forward_iterator_tag) { // No checks } template<class It, class Predicate> Bounds<It> findBounds(It first, It last, Predicate p, std::random_access_iterator_tag) { // No checks smart } template<class It, class Predicate> Bounds<It> findBounds(It first, It last, Predicate p) { return findBounds(first, last, p, std::iterator_traits<It>::iterator_category{}); } Tag dispatching Mikhail Matrosov, Versatile C++, CoreHard 2018 85
  • 86. Mikhail Matrosov, Versatile C++, CoreHard 2018 86
  • 87. Computational complexity • 87Mikhail Matrosov, Versatile C++, CoreHard 2018
  • 88. 88 10 32 54 76 98 1110 1312 1410 32 54 76 98 1110 1312 14 Complexity of findAny() Mikhail Matrosov, Versatile C++, CoreHard 2018
  • 89. Computational complexity • 89Mikhail Matrosov, Versatile C++, CoreHard 2018
  • 90. • 90Mikhail Matrosov, Versatile C++, CoreHard 2018
  • 92. 92Mikhail Matrosov, Versatile C++, CoreHard 2018
  • 93. Method Input Output Modify input Check structure Assume layout Copy const vector& vector no yes no Reuse vector&& vector yes yes no Reuse smart vector&& vector yes yes no Reuse std::list list&& list yes yes no boost.range vector boost::range::joined_range no yes no WrappingIterator vector boost::iterator_range<WrappingIterator> no yes no Generic pair of iterators boost::range::joined_range no yes no Range-V3-VS2015 pair of iterators ranges::concat_view no yes no VC++ generator pair of iterators std::generator no yes no No checks pair of iterators boost::range::joined_range no no no No checks smart pair of random- access iterators boost::range::joined_range no no yes 93Mikhail Matrosov, Versatile C++, CoreHard 2018
  • 94. Mikhail Matrosov, Versatile C++, CoreHard 2018 Take aways • Analyze! Keyboard after paper • Recognize patterns, implement them with standard algorithms • Think about the interface • Don’t be afraid to go generic • Use modern C++ • Care about asymptotic complexity • Measure performance 94 Questions?