68
Повседневный С++: алгоритмы и итераторы Михаил Матросов [email protected] [email protected] 1

Повседневный С++: алгоритмы и итераторы

Embed Size (px)

Citation preview

Page 1: Повседневный С++: алгоритмы и итераторы

Повседневный С++: алгоритмы и итераторы

Михаил Матросов[email protected]

[email protected]

1

Page 2: Повседневный С++: алгоритмы и итераторы

"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, C++ CoreHard Winter 2017 Сonference

2

Page 3: Повседневный С++: алгоритмы и итераторы

goo.gl/TL15Rg

"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, C++ CoreHard Winter 2017 Сonference

3"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, C++ CoreHard Winter 2017 Сonference

3

С++17С++11/14

С++98

С

High level

Expert level

Modern C++

Almost the same :(

Page 4: Повседневный С++: алгоритмы и итераторы

“Within C++ is a smaller, simpler, safer language struggling to get out”

Bjarne Stroustrup

"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, C++ CoreHard Winter 2017 Сonference

4

Page 5: Повседневный С++: алгоритмы и итераторы

High level: Парадигма RAII и исключения (exceptions) Семантика перемещения λ-функции Классы и конструкторы Простые шаблоны STL Утилиты и алгоритмы boost

"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, C++ CoreHard Winter 2017 Сonference

5

Expert level: Операторы new/delete, владеющие

указатели Пользовательские операции копирования

и перемещения Пользовательские деструкторы Закрытое, защищённое, ромбовидное,

виртуальное наследование Шаблонная магия Все функции языка Си, препроцессор «Голые» циклы

Классический слайд с телом и заголовком

Page 7: Повседневный С++: алгоритмы и итераторы

const std::vector<Point> extract(const std::vector<Point>& points){  std::vector<Point> result;  result.clear();   if (points.size() == 0)    return result;   int p = 0;  bool found = false;  for (int i = 1; i < points.size() && ~found; ++i)    if (points[i - 1].x < 0 && points[i].x >= 0)    {      p = i;      found = true;    }   int q = 0;  found = false;  for (int i = 1; i < points.size() && ~found; ++i)    if (points[i - 1].x >= 0 && points[i].x < 0)    {      q = i;      found = true;    }   if (p == q)  {    if ((*points.begin()).x >= 0)      return points;    else      return result;  }   int i = p;  while (i != q)  {    if (points[i].x < 0)    {      result.clear();      Point nan;      nan.x = sqrt(-1);      nan.y = sqrt(-1);      result.push_back(nan);      return result;    }    result.push_back(points[i]);    if (++i >= points.size())      i = 0;  }   i = q;  while (i != p)  {    if (points[i].x >= 0)    {      result.clear();      Point nan;      nan.x = sqrt(-1);      nan.y = sqrt(-1);      result.push_back(nan);      return result;    }    if (++i >= points.size())      i = 0;  }   return std::move(result);}

7

Page 8: Повседневный С++: алгоритмы и итераторы

"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, C++ CoreHard Winter 2017 Сonference

8

const std::vector<Point> extract(const std::vector<Point>& points){  std::vector<Point> result;  result.clear();   if (points.size() == 0)    return result;   int p = 0;  bool found = false;  for (int i = 1; i < points.size() && ~found; ++i)    if (points[i - 1].x < 0 && points[i].x >= 0)    {      p = i;      found = true;    }   int q = 0;  found = false;  for (int i = 1; i < points.size() && ~found; ++i)    if (points[i - 1].x >= 0 && points[i].x < 0)    {      q = i;      found = true;    }   if (p == q)  {    if ((*points.begin()).x >= 0)      return points;    else      return result;  }   int i = p;  while (i != q)  {    if (points[i].x < 0)    {      result.clear();      Point nan;      nan.x = sqrt(-1);      nan.y = sqrt(-1);      result.push_back(nan);      return result;    }    result.push_back(points[i]);    if (++i >= points.size())      i = 0;  }   i = q;  while (i != p)  {    if (points[i].x >= 0)    {      result.clear();      Point nan;      nan.x = sqrt(-1);      nan.y = sqrt(-1);      result.push_back(nan);      return result;    }    if (++i >= points.size())      i = 0;  }   return std::move(result);}

std::vector<Point> extractRight(std::vector<Point> points){  using namespace boost::range;  using namespace boost::algorithm;   auto isRight = [](const Point& pt) { return pt.x >= 0; };   auto middle = adjacent_find(points,    [&](auto&& pt1, auto&& pt2) { return !isRight(pt1) && isRight(pt2); });   if (middle != points.end())    rotate(points, std::next(middle));   if (!is_partitioned(points, isRight))    throw std::runtime_error("Unexpected order");   points.erase(partition_point(points, isRight), points.end());   return points;}

Page 9: Повседневный С++: алгоритмы и итераторы

"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, C++ CoreHard Winter 2017 Сonference

9

const std::vector<Point> extract(const std::vector<Point>& points){

Page 10: Повседневный С++: алгоритмы и итераторы

"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, C++ CoreHard Winter 2017 Сonference

10

std::vector<Point> extract(const std::vector<Point>& points){

Page 11: Повседневный С++: алгоритмы и итераторы

"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, C++ CoreHard Winter 2017 Сonference

11

std::vector<Point> extract(const std::vector<Point>& points){  std::vector<Point> result;  result.clear();

Page 12: Повседневный С++: алгоритмы и итераторы

"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, C++ CoreHard Winter 2017 Сonference

12

std::vector<Point> extract(const std::vector<Point>& points){  std::vector<Point> result;

Page 13: Повседневный С++: алгоритмы и итераторы

"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, C++ CoreHard Winter 2017 Сonference

13

std::vector<Point> extract(const std::vector<Point>& points){  std::vector<Point> result;   if (points.size() == 0)    return result;

Page 14: Повседневный С++: алгоритмы и итераторы

"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, C++ CoreHard Winter 2017 Сonference

14

std::vector<Point> extract(const std::vector<Point>& points){  std::vector<Point> result;   if (points.empty())    return result;

Page 15: Повседневный С++: алгоритмы и итераторы

"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, C++ CoreHard Winter 2017 Сonference

15

std::vector<Point> extract(const std::vector<Point>& points){  std::vector<Point> result;   if (points.empty())    return result;   int p = 0;  bool found = false;  for (int i = 1; i < points.size() && ~found; ++i)    if (points[i - 1].x < 0 && points[i].x >= 0)    {      p = i;      found = true;    }

Page 16: Повседневный С++: алгоритмы и итераторы

"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, C++ CoreHard Winter 2017 Сonference

16

std::vector<Point> extract(const std::vector<Point>& points){  std::vector<Point> result;   if (points.empty())    return result;   int p = 0;  bool found = false;  for (int i = 1; i < points.size() && !found; ++i)    if (points[i - 1].x < 0 && points[i].x >= 0)    {      p = i;      found = true;    }

Page 17: Повседневный С++: алгоритмы и итераторы

"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, C++ CoreHard Winter 2017 Сonference

17

std::vector<Point> extract(const std::vector<Point>& points){  std::vector<Point> result;   if (points.empty())    return result;   int p = 0;  bool found = false;  for (int i = 1; i < points.size(); ++i)    if (points[i - 1].x < 0 && points[i].x >= 0)    {      p = i;      break;    }

Page 18: Повседневный С++: алгоритмы и итераторы

"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, C++ CoreHard Winter 2017 Сonference

18

  int p = 0;  for (int i = 1; i < points.size(); ++i)    if (points[i - 1].x < 0 && points[i].x >= 0)    {      p = i;      break;    }   int q = 0;  for (int i = 1; i < points.size(); ++i)    if (points[i - 1].x >= 0 && points[i].x < 0)    {      q = i;      break;    }

Page 19: Повседневный С++: алгоритмы и итераторы

"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, C++ CoreHard Winter 2017 Сonference

19

auto isRight = [](const Point& pt) { return pt.x >= 0; };   int p = 0;  for (int i = 1; i < points.size(); ++i)    if (!isRight(points[i - 1]) && isRight(points[i]))    {      p = i;      break;    }   int q = 0;  for (int i = 1; i < points.size(); ++i)    if (isRight(points[i - 1]) && !isRight(points[i]))    {      q = i;      break;    }

Page 20: Повседневный С++: алгоритмы и итераторы

"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, C++ CoreHard Winter 2017 Сonference

20

  auto isRight = [](const Point& pt) { return pt.x >= 0; };   auto find = [&](bool flag)  {    for (int i = 1; i < points.size(); ++i)      if (isRight(points[i - 1]) == flag &&  isRight(points[i]) != flag)        return i;    return 0;  };   int p = find(false);  int q = find(true);

Page 21: Повседневный С++: алгоритмы и итераторы

"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, C++ CoreHard Winter 2017 Сonference

21

  auto isRight = [](const Point& pt) { return pt.x >= 0; };   auto findBoundary = [&](bool rightToLeft)  {    for (int i = 1; i < points.size(); ++i)      if (isRight(points[i - 1]) == rightToLeft &&  isRight(points[i]) != rightToLeft)        return i;    return 0;  };   int p = findBoundary(false);  int q = findBoundary(true);

Page 22: Повседневный С++: алгоритмы и итераторы

"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, C++ CoreHard Winter 2017 Сonference

22

  int p = findBoundary(false);  int q = findBoundary(true);   if (p == q)  {    if (isRight(*points.begin()))      return points;    else      return result;  }

Page 23: Повседневный С++: алгоритмы и итераторы

"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, C++ CoreHard Winter 2017 Сonference

23

  int p = findBoundary(false);  int q = findBoundary(true);   if (p == q)  {    if (isRight(points[0]))      return points;    else      return result;  }

Page 24: Повседневный С++: алгоритмы и итераторы

"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, C++ CoreHard Winter 2017 Сonference

24

  int p = findBoundary(false);  int q = findBoundary(true);   if (p == q)    return isRight(points[0]) ? points : result;

Page 25: Повседневный С++: алгоритмы и итераторы

"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, C++ CoreHard Winter 2017 Сonference

25

  if (p == q)    return isRight(points[0]) ? points : result;   int i = p;  while (i != q)  {    if (!isRight(points[i]))    {      result.clear();      Point nan;      nan.x = sqrt(-1);      nan.y = sqrt(-1);      result.push_back(nan);      return result;    }    result.push_back(points[i]);    if (++i >= points.size())      i = 0;  }

Page 26: Повседневный С++: алгоритмы и итераторы

"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, C++ CoreHard Winter 2017 Сonference

26

  if (p == q)    return isRight(points[0]) ? points : result;   int i = p;  while (i != q)  {    if (!isRight(points[i]))      return { Point(NAN, NAN) };    result.push_back(points[i]);    if (++i >= points.size())      i = 0;  }

std::numeric_limits::quiet_NaN() vs. std::nan() vs. NAN

Page 27: Повседневный С++: алгоритмы и итераторы

"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, C++ CoreHard Winter 2017 Сonference

27

  int i = p;  while (i != q)  {    if (!isRight(points[i]))      return { Point(NAN, NAN) };    result.push_back(points[i]);    if (++i >= points.size())      i = 0;  }   i = q;  while (i != p)  {    if (isRight(points[i]))      return { Point(NAN, NAN) };    if (++i >= points.size())      i = 0;  }

Page 28: Повседневный С++: алгоритмы и итераторы

"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, C++ CoreHard Winter 2017 Сonference

28

  int i = p;  while (i != q)  {    if (!isRight(points[i]))      return { Point(NAN, NAN) };    result.push_back(points[i]);    if (++i >= points.size())      i = 0;  }   i = q;  while (i != p)  {    if (isRight(points[i]))      return { Point(NAN, NAN) };    if (++i >= points.size())      i = 0;  }

Page 29: Повседневный С++: алгоритмы и итераторы

"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, C++ CoreHard Winter 2017 Сonference

29

  auto appendResult = [&](int from, int to, bool shouldBeRight)  {    int i = from;    while (i != to)    {      if (isRight(points[i]) != shouldBeRight)      {        result = { Point(NAN, NAN) };        return false;      }      if (shouldBeRight)        result.push_back(points[i]);      if (++i >= points.size())        i = 0;    }    return true;  };   bool success = appendResult(p, q, true) && appendResult(q, p, false);

Page 30: Повседневный С++: алгоритмы и итераторы

"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, C++ CoreHard Winter 2017 Сonference

30

  auto appendResult = [&](int from, int to, bool shouldBeRight)  {    int i = from;    while (i != to)    {      if (isRight(points[i]) != shouldBeRight)        throw std::runtime_error("Unexpected order");      if (shouldBeRight)        result.push_back(points[i]);      if (++i >= points.size())        i = 0;    }  };   appendResult(p, q, true);  appendResult(q, p, false);

Page 31: Повседневный С++: алгоритмы и итераторы

"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, C++ CoreHard Winter 2017 Сonference

31

  appendResult(p, q, true);  appendResult(q, p, false);   return std::move(result);}

Page 32: Повседневный С++: алгоритмы и итераторы

"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, C++ CoreHard Winter 2017 Сonference

32

  appendResult(p, q, true);  appendResult(q, p, false);   return result;}

Page 33: Повседневный С++: алгоритмы и итераторы

"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, C++ CoreHard Winter 2017 Сonference

33

std::vector<Point> extract(const std::vector<Point>& points){  std::vector<Point> result;   if (points.empty())    return result;   auto isRight = [](const Point& pt) { return pt.x >= 0; };   auto findBoundary = [&](bool rightToLeft)  {    for (int i = 1; i < points.size(); ++i)      if (isRight(points[i - 1]) == rightToLeft &&           isRight(points[i]) != rightToLeft)        return i;    return 0;  };   int p = findBoundary(false);  int q = findBoundary(true);   if (p == q)    return isRight(points[0]) ? points : result;   auto appendResult = [&](int from, int to, bool shouldBeRight)  {    int i = from;    while (i != to)    {      if (isRight(points[i]) != shouldBeRight)        throw std::runtime_error("Unexpected order");      if (shouldBeRight)        result.push_back(points[i]);      if (++i >= points.size())        i = 0;    }  };   appendResult(p, q, true);  appendResult(q, p, false);   return result;}

const std::vector<Point> extract(const std::vector<Point>& points){  std::vector<Point> result;  result.clear();   if (points.size() == 0)    return result;   int p = 0;  bool found = false;  for (int i = 1; i < points.size() && ~found; ++i)    if (points[i - 1].x < 0 && points[i].x >= 0)    {      p = i;      found = true;    }   int q = 0;  found = false;  for (int i = 1; i < points.size() && ~found; ++i)    if (points[i - 1].x >= 0 && points[i].x < 0)    {      q = i;      found = true;    }   if (p == q)  {    if ((*points.begin()).x >= 0)      return points;    else      return result;  }   int i = p;  while (i != q)  {    if (points[i].x < 0)    {      result.clear();      Point nan;      nan.x = sqrt(-1);      nan.y = sqrt(-1);      result.push_back(nan);      return result;    }    result.push_back(points[i]);    if (++i >= points.size())      i = 0;  }   i = q;  while (i != p)  {    if (points[i].x >= 0)    {      result.clear();      Point nan;      nan.x = sqrt(-1);      nan.y = sqrt(-1);      result.push_back(nan);      return result;    }    if (++i >= points.size())      i = 0;  }   return std::move(result);}

int p = findBoundary(false);int q = findBoundary(true);

appendResult(p, q, true);appendResult(q, p, false);

Page 34: Повседневный С++: алгоритмы и итераторы

"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, C++ CoreHard Winter 2017 Сonference

34

0 1 2 3 4 5 6 1 2 3 4

0 1 2 3 4 5 6

qp

p q

0 1 2 3 4 5 6 4 5 6 0 1

pq

Page 35: Повседневный С++: алгоритмы и итераторы

"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, C++ CoreHard Winter 2017 Сonference

35

0 1 2 3 4 5 6

1. Найти первый элемент2. Сдвинуть его в началоp

Page 36: Повседневный С++: алгоритмы и итераторы

"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, C++ CoreHard Winter 2017 Сonference

36

6 0 1 2 3 4 5

1. Найти первый элемент2. Сдвинуть его в начало

Page 37: Повседневный С++: алгоритмы и итераторы

"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, C++ CoreHard Winter 2017 Сonference

37

5 6 0 1 2 3 4

1. Найти первый элемент2. Сдвинуть его в начало

Page 38: Повседневный С++: алгоритмы и итераторы

"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, C++ CoreHard Winter 2017 Сonference

38

5 6 0 1 2 34

1. Найти первый элемент2. Сдвинуть его в начало3. Проверить структуру4. Выкинуть хвост5. Вернуть что осталось

Page 39: Повседневный С++: алгоритмы и итераторы

std::vector<Point> extractRight(std::vector<Point> points){

"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, C++ CoreHard Winter 2017 Сonference

39

Page 40: Повседневный С++: алгоритмы и итераторы

std::vector<Point> extractRight(std::vector<Point> points){  using namespace boost::range;  using namespace boost::algorithm;   auto isRight = [](const Point& pt) { return pt.x >= 0; };

"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, C++ CoreHard Winter 2017 Сonference

40

Page 41: Повседневный С++: алгоритмы и итераторы

std::vector<Point> extractRight(std::vector<Point> points){  using namespace boost::range;  using namespace boost::algorithm;   auto isRight = [](const Point& pt) { return pt.x >= 0; };   auto middle = adjacent_find(points,    [&](auto&& pt1, auto&& pt2) { return !isRight(pt1) && isRight(pt2); });

"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, C++ CoreHard Winter 2017 Сonference

41

Page 42: Повседневный С++: алгоритмы и итераторы

std::vector<Point> extractRight(std::vector<Point> points){  using namespace boost::range;  using namespace boost::algorithm;   auto isRight = [](const Point& pt) { return pt.x >= 0; };   auto middle = adjacent_find(points,    [&](auto&& pt1, auto&& pt2) { return !isRight(pt1) && isRight(pt2); });   if (middle != points.end())    rotate(points, std::next(middle));

"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, C++ CoreHard Winter 2017 Сonference

42

Page 43: Повседневный С++: алгоритмы и итераторы

std::vector<Point> extractRight(std::vector<Point> points){  using namespace boost::range;  using namespace boost::algorithm;   auto isRight = [](const Point& pt) { return pt.x >= 0; };   auto middle = adjacent_find(points,    [&](auto&& pt1, auto&& pt2) { return !isRight(pt1) && isRight(pt2); });   if (middle != points.end())    rotate(points, std::next(middle));   if (!is_partitioned(points, isRight))    throw std::runtime_error("Unexpected order");

"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, C++ CoreHard Winter 2017 Сonference

43

Page 44: Повседневный С++: алгоритмы и итераторы

std::vector<Point> extractRight(std::vector<Point> points){  using namespace boost::range;  using namespace boost::algorithm;   auto isRight = [](const Point& pt) { return pt.x >= 0; };   auto middle = adjacent_find(points,    [&](auto&& pt1, auto&& pt2) { return !isRight(pt1) && isRight(pt2); });   if (middle != points.end())    rotate(points, std::next(middle));   if (!is_partitioned(points, isRight))    throw std::runtime_error("Unexpected order");   points.erase(partition_point(points, isRight), points.end());

"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, C++ CoreHard Winter 2017 Сonference

44

Page 45: Повседневный С++: алгоритмы и итераторы

std::vector<Point> extractRight(std::vector<Point> points){  using namespace boost::range;  using namespace boost::algorithm;   auto isRight = [](const Point& pt) { return pt.x >= 0; };   auto middle = adjacent_find(points,    [&](auto&& pt1, auto&& pt2) { return !isRight(pt1) && isRight(pt2); });   if (middle != points.end())    rotate(points, std::next(middle));   if (!is_partitioned(points, isRight))    throw std::runtime_error("Unexpected order");   points.erase(partition_point(points, isRight), points.end());   return points;}

"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, C++ CoreHard Winter 2017 Сonference

45

Page 46: Повседневный С++: алгоритмы и итераторы

"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, C++ CoreHard Winter 2017 Сonference

46

const std::vector<Point> extract(const std::vector<Point>& points){  std::vector<Point> result;  result.clear();   if (points.size() == 0)    return result;   int p = 0;  bool found = false;  for (int i = 1; i < points.size() && ~found; ++i)    if (points[i - 1].x < 0 && points[i].x >= 0)    {      p = i;      found = true;    }   int q = 0;  found = false;  for (int i = 1; i < points.size() && ~found; ++i)    if (points[i - 1].x >= 0 && points[i].x < 0)    {      q = i;      found = true;    }   if (p == q)  {    if ((*points.begin()).x >= 0)      return points;    else      return result;  }   int i = p;  while (i != q)  {    if (points[i].x < 0)    {      result.clear();      Point nan;      nan.x = sqrt(-1);      nan.y = sqrt(-1);      result.push_back(nan);      return result;    }    result.push_back(points[i]);    if (++i >= points.size())      i = 0;  }   i = q;  while (i != p)  {    if (points[i].x >= 0)    {      result.clear();      Point nan;      nan.x = sqrt(-1);      nan.y = sqrt(-1);      result.push_back(nan);      return result;    }    if (++i >= points.size())      i = 0;  }   return std::move(result);}

std::vector<Point> extractRight(std::vector<Point> points){  using namespace boost::range;  using namespace boost::algorithm;   auto isRight = [](const Point& pt) { return pt.x >= 0; };   auto middle = adjacent_find(points,    [&](auto&& pt1, auto&& pt2) { return !isRight(pt1) && isRight(pt2); });   if (middle != points.end())    rotate(points, std::next(middle));   if (!is_partitioned(points, isRight))    throw std::runtime_error("Unexpected order");   points.erase(partition_point(points, isRight), points.end());   return points;}

std::vector<Point> extract(const std::vector<Point>& points){  std::vector<Point> result;   if (points.empty())    return result;   auto isRight = [](const Point& pt) { return pt.x >= 0; };   auto findBoundary = [&](bool rightToLeft)  {    for (int i = 1; i < points.size(); ++i)      if (isRight(points[i - 1]) == rightToLeft &&           isRight(points[i]) != rightToLeft)        return i;    return 0;  };   int p = findBoundary(false);  int q = findBoundary(true);   if (p == q)    return isRight(points[0]) ? points : result;   auto appendResult = [&](int from, int to, bool shouldBeRight)  {    int i = from;    while (i != to)    {      if (isRight(points[i]) != shouldBeRight)        throw std::runtime_error("Unexpected order");      if (shouldBeRight)        result.push_back(points[i]);      if (++i >= points.size())        i = 0;    }  };   appendResult(p, q, true);  appendResult(q, p, false);   return result;}

Page 47: Повседневный С++: алгоритмы и итераторы

"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, C++ CoreHard Winter 2017 Сonference

47

0 1 2 3

middlefirst last

4 5 6

Page 48: Повседневный С++: алгоритмы и итераторы

"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, C++ CoreHard Winter 2017 Сonference

48

Sean Parent: C++ Seasoning (no raw loops)

Page 49: Повседневный С++: алгоритмы и итераторы

"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, C++ CoreHard Winter 2017 Сonference

49

Page 50: Повседневный С++: алгоритмы и итераторы

"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, C++ CoreHard Winter 2017 Сonference

50

Page 51: Повседневный С++: алгоритмы и итераторы

0 1 2 3 4 5 6 0 1 2 3 4

"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, C++ CoreHard Winter 2017 Сonference

51

0 1 2 3 4 5 6

Ответ!

Результат rotate()!

Page 52: Повседневный С++: алгоритмы и итераторы

"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, C++ CoreHard Winter 2017 Сonference

52

template<class It>class WrappingIterator : public boost::iterator_adaptor<WrappingIterator<It>, It>{  using Base = boost::iterator_adaptor<WrappingIterator<It>, It>; public:  WrappingIterator() = default;  WrappingIterator(It it, It begin, It end) :     Base(it), m_begin(begin), m_size(end - begin) {} private:  friend class boost::iterator_core_access;   typename Base::reference dereference() const  {    return *(m_begin + (this->base_reference() - m_begin) % m_size);  }   It m_begin;  size_t m_size;};

Page 53: Повседневный С++: алгоритмы и итераторы

"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, C++ CoreHard Winter 2017 Сonference

53

template<class It>auto makeWrappingIterator(It it, It begin, It end){  return WrappingIterator<It>(it, begin, end);}

Page 54: Повседневный С++: алгоритмы и итераторы

"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, C++ CoreHard Winter 2017 Сonference

54

auto extractRight(const std::vector<Point>& points){

Page 55: Повседневный С++: алгоритмы и итераторы

"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, C++ CoreHard Winter 2017 Сonference

55

auto extractRight(const std::vector<Point>& points){  using namespace boost;   auto isRight = [](const Point& pt) { return pt.x >= 0; };   auto middle = adjacent_find(points,    [&](auto&& pt1, auto&& pt2) { return !isRight(pt1) && isRight(pt2); });

Page 56: Повседневный С++: алгоритмы и итераторы

"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, C++ CoreHard Winter 2017 Сonference

56

auto extractRight(const std::vector<Point>& points){  using namespace boost;   auto isRight = [](const Point& pt) { return pt.x >= 0; };   auto middle = adjacent_find(points,    [&](auto&& pt1, auto&& pt2) { return !isRight(pt1) && isRight(pt2); });   middle = middle != points.end() ? std::next(middle) : points.begin();   auto begin = makeWrappingIterator(middle, points.begin(), points.end());  auto end = begin + points.size();

Page 57: Повседневный С++: алгоритмы и итераторы

"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, C++ CoreHard Winter 2017 Сonference

57

auto extractRight(const std::vector<Point>& points){  using namespace boost;   auto isRight = [](const Point& pt) { return pt.x >= 0; };   auto middle = adjacent_find(points,    [&](auto&& pt1, auto&& pt2) { return !isRight(pt1) && isRight(pt2); });   middle = middle != points.end() ? std::next(middle) : points.begin();   auto begin = makeWrappingIterator(middle, points.begin(), points.end());  auto end = begin + points.size();   if (!is_partitioned(begin, end, isRight))    throw std::runtime_error("Unexpected order");

Page 58: Повседневный С++: алгоритмы и итераторы

"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, C++ CoreHard Winter 2017 Сonference

58

auto extractRight(const std::vector<Point>& points){  using namespace boost;   auto isRight = [](const Point& pt) { return pt.x >= 0; };   auto middle = adjacent_find(points,    [&](auto&& pt1, auto&& pt2) { return !isRight(pt1) && isRight(pt2); });   middle = middle != points.end() ? std::next(middle) : points.begin();   auto begin = makeWrappingIterator(middle, points.begin(), points.end());  auto end = begin + points.size();   if (!is_partitioned(begin, end, isRight))    throw std::runtime_error("Unexpected order");   end = partition_point(begin, end, isRight);

Page 59: Повседневный С++: алгоритмы и итераторы

"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, C++ CoreHard Winter 2017 Сonference

59

auto extractRight(const std::vector<Point>& points){  using namespace boost;   auto isRight = [](const Point& pt) { return pt.x >= 0; };   auto middle = adjacent_find(points,    [&](auto&& pt1, auto&& pt2) { return !isRight(pt1) && isRight(pt2); });   middle = middle != points.end() ? std::next(middle) : points.begin();   auto begin = makeWrappingIterator(middle, points.begin(), points.end());  auto end = begin + points.size();   if (!is_partitioned(begin, end, isRight))    throw std::runtime_error("Unexpected order");   end = partition_point(begin, end, isRight);   return boost::make_iterator_range(begin, end);}

Page 60: Повседневный С++: алгоритмы и итераторы

"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, C++ CoreHard Winter 2017 Сonference

60

0 1 2 3 4 5 6

Раз……два!

Page 61: Повседневный С++: алгоритмы и итераторы

"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, C++ CoreHard Winter 2017 Сonference

61

template<class It, class Predicate>auto extractIf(It first, It last, Predicate p){

Page 62: Повседневный С++: алгоритмы и итераторы

"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, C++ CoreHard Winter 2017 Сonference

62

template<class It, class Predicate>auto extractIf(It first, It last, Predicate p){  using namespace boost::range;  using namespace boost::algorithm;   auto middle = adjacent_find(first, last,    [&](auto&& a, auto&& b) { return !p(a) && p(b); });   middle = middle != last ? std::next(middle) : first;

Page 63: Повседневный С++: алгоритмы и итераторы

"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, C++ CoreHard Winter 2017 Сonference

63

template<class It, class Predicate>auto extractIf(It first, It last, Predicate p){  using namespace boost::range;  using namespace boost::algorithm;   auto middle = adjacent_find(first, last,    [&](auto&& a, auto&& b) { return !p(a) && p(b); });   middle = middle != last ? std::next(middle) : first;   auto rotated = boost::join(boost::make_iterator_range(middle, last),      boost::make_iterator_range(first, middle));

Page 64: Повседневный С++: алгоритмы и итераторы

"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, C++ CoreHard Winter 2017 Сonference

64

template<class It, class Predicate>auto extractIf(It first, It last, Predicate p){  using namespace boost::range;  using namespace boost::algorithm;   auto middle = adjacent_find(first, last,    [&](auto&& a, auto&& b) { return !p(a) && p(b); });   middle = middle != last ? std::next(middle) : first;   auto rotated = boost::join(boost::make_iterator_range(middle, last),      boost::make_iterator_range(first, middle));   if (!is_partitioned(rotated, p))    throw std::runtime_error("Unexpected order");

Page 65: Повседневный С++: алгоритмы и итераторы

"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, C++ CoreHard Winter 2017 Сonference

65

template<class It, class Predicate>auto extractIf(It first, It last, Predicate p){  using namespace boost::range;  using namespace boost::algorithm;   auto middle = adjacent_find(first, last,    [&](auto&& a, auto&& b) { return !p(a) && p(b); });   middle = middle != last ? std::next(middle) : first;   auto rotated = boost::join(boost::make_iterator_range(middle, last),      boost::make_iterator_range(first, middle));   if (!is_partitioned(rotated, p))    throw std::runtime_error("Unexpected order");   auto end = partition_point(rotated, p);

Page 66: Повседневный С++: алгоритмы и итераторы

"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, C++ CoreHard Winter 2017 Сonference

66

template<class It, class Predicate>auto extractIf(It first, It last, Predicate p){  using namespace boost::range;  using namespace boost::algorithm;   auto middle = adjacent_find(first, last,    [&](auto&& a, auto&& b) { return !p(a) && p(b); });   middle = middle != last ? std::next(middle) : first;   auto rotated = boost::join(boost::make_iterator_range(middle, last),      boost::make_iterator_range(first, middle));   if (!is_partitioned(rotated, p))    throw std::runtime_error("Unexpected order");   auto end = partition_point(rotated, p);   return boost::make_iterator_range(rotated.begin(), end);}

Page 67: Повседневный С++: алгоритмы и итераторы

Ответь на вопросПолучи мячик…PROFIT!

"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, C++ CoreHard Winter 2017 Сonference

67

Page 68: Повседневный С++: алгоритмы и итераторы

"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, C++ CoreHard Winter 2017 Сonference

68

Мыслите в терминах алгоритмовКод должен ясно выражать намерениеЗнайте свои инструменты и используйте их к месту

// lambda functions (including generic)// ternary operator// exceptions// transient parametersstd::vector<T>::empty()adjacent_find()rotate()is_partitioned()partition_point()std::next();

// custom make-function// template parameters for iterators// template parameters for predicates// function return type deduction boost::rangeboost::algorithmboost::iterator_adaptor<It>boost::make_iterator_range()boost::join()

Спасибо за внимание!