SlideShare a Scribd company logo
#SECONRU
Повседневный С++:
алгоритмы и итераторы
Матросов Михаил
Технический менеджер, Align Technology
Москва
"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 2
"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 33
С++17
С++11/14
С++98
С
High level
Expert level
Modern C++
Almost the same :(
“Within C++ is a smaller, simpler, safer
language struggling to get out”
Bjarne Stroustrup
"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 4
High level:
 Парадигма RAII и исключения (exceptions)
 Семантика перемещения
 λ-функции
 Классы и конструкторы
 Простые шаблоны
 STL
 Утилиты и алгоритмы boost
"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 5
Expert level:
 Операторы new/delete, владеющие
указатели
 Пользовательские операции копирования
и перемещения
 Пользовательские деструкторы
 Закрытое, защищённое, ромбовидное,
виртуальное наследование
 Шаблонная магия
 Все функции языка Си, препроцессор
 «Голые» циклы
6
Which boost
features overlap
with C++11?
План действий
 Рассмотрим пример реального кода
 Вместе выполним рефакторинг
 Перепишем с нуля
 Обобщим решение
"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 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) 8
"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 9
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); });
middle = middle != points.end() ? std::next(middle) : points.begin();
rotate(points, middle);
if (!is_partitioned(points, isRight))
throw std::runtime_error("Unexpected order");
points.erase(partition_point(points, isRight), points.end());
return points;
}
"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 10
const std::vector<Point> extract(const std::vector<Point>& points)
{
"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 11
std::vector<Point> extract(const std::vector<Point>& points)
{
"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 12
std::vector<Point> extract(const std::vector<Point>& points)
{
std::vector<Point> result;
result.clear();
"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 13
std::vector<Point> extract(const std::vector<Point>& points)
{
std::vector<Point> result;
"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 14
std::vector<Point> extract(const std::vector<Point>& points)
{
std::vector<Point> result;
if (points.size() == 0)
return result;
"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 15
std::vector<Point> extract(const std::vector<Point>& points)
{
std::vector<Point> result;
if (points.empty())
return result;
"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 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;
}
"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 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;
}
"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 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;
}
"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 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;
}
"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 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);
"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 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);
"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 22
int p = findBoundary(false);
int q = findBoundary(true);
if (p == q)
{
if (isRight(*points.begin()))
return points;
else
return result;
}
"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 23
int p = findBoundary(false);
int q = findBoundary(true);
if (p == q)
{
if (isRight(points[0]))
return points;
else
return result;
}
"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 24
int p = findBoundary(false);
int q = findBoundary(true);
if (p == q)
return isRight(points[0]) ? points : result;
"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 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;
}
"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 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
"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 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;
}
"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 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;
}
"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 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);
"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 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);
"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 31
appendResult(p, q, true);
appendResult(q, p, false);
return std::move(result);
}
"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 32
appendResult(p, q, true);
appendResult(q, p, false);
return result;
}
"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 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);
"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 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
"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 35
0 1 2 3 4 5 6
1. Найти первый элемент
2. Сдвинуть его в началоp
"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 36
6 0 1 2 3 4 5
1. Найти первый элемент
2. Сдвинуть его в начало
"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 37
5 6 0 1 2 3 4
1. Найти первый элемент
2. Сдвинуть его в начало
"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 38
5 6 0 1 2 34
1. Найти первый элемент
2. Сдвинуть его в начало
3. Проверить структуру
4. Выкинуть хвост
5. Вернуть что осталось
std::vector<Point> extractRight(std::vector<Point> points)
{
"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 39
0 1 2 3 4 5 6
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; };
"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 40
0 1 2 3 4 5 6
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); });
middle = middle != points.end() ? std::next(middle) : points.begin();
"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 41
0 1 2 3 4 5 6
middle
42
5 6 0 1 2 34
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); });
middle = middle != points.end() ? std::next(middle) : points.begin();
rotate(points, middle);
"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017
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); });
middle = middle != points.end() ? std::next(middle) : points.begin();
rotate(points, middle);
if (!is_partitioned(points, isRight))
throw std::runtime_error("Unexpected order");
"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 43
5 6 0 1 2 34
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); });
middle = middle != points.end() ? std::next(middle) : points.begin();
rotate(points, middle);
if (!is_partitioned(points, isRight))
throw std::runtime_error("Unexpected order");
points.erase(partition_point(points, isRight), points.end());
"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 44
5 6 0 14
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); });
middle = middle != points.end() ? std::next(middle) : points.begin();
rotate(points, middle);
if (!is_partitioned(points, isRight))
throw std::runtime_error("Unexpected order");
points.erase(partition_point(points, isRight), points.end());
return points;
}
"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 45
5 6 0 14
"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 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;
}
"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 47
// Two specialized overloads
std::vector<Point> extractRight(std::vector<Point>&& points)
{
// Process points in-place...
return points;
}
std::vector<Point> extractRight(const std::vector<Point>& points)
{
std::vector<Point> result = points; // Might be altered!
// Process result...
return result;
}
// One universal function
std::vector<Point> extractRight(std::vector<Point> points)
{
// Process points in-place...
return points;
}
"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 48
0 1 2 3
middlefirst last
4 5 6
"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 49
Sean Parent: C++ Seasoning (no raw loops)
"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 50
"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 51
Обобщаем!
 std::vector → последовательность (пара итераторов)
 isRight() → предикат
 Результат как копия → результат как подпоследовательность
"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 52
"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 53
0 1 2 3 4 5 6
Раз……два!
"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 54
template<class It, class Predicate>
auto extractIf(It first, It last, Predicate p)
{
0 1 2 3 4 5 6
first last
"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 55
template<class It, class Predicate>
auto extractIf(It first, It last, Predicate p)
{
using namespace boost::range;
using namespace boost::algorithm;
0 1 2 3 4 5 6
first last
"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 56
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;
0 1 2 3 4 5 6
first lastmiddle
"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 57
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));
0 1 2 3 4 5 6
first lastmiddle
"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 58
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");
0 1 2 3 4 5 6
first lastmiddle
"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 59
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);
0 1 2 3 4 5 6
first lastmiddleend
"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 60
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);
}
0 1 2 3 4 5 6
first lastmiddleend
"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 61
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);
}
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);
});
middle = middle != points.end() ? std::next(middle)
: points.begin();
rotate(points, middle);
if (!is_partitioned(points, isRight))
throw std::runtime_error("Unexpected order");
points.erase(
partition_point(points, isRight), points.end());
return points;
}
 Ответь на вопрос
 Получи мячик
 …
 PROFIT!
"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 62
Performance?
Range Traverse time
std::vector 1.0
Joined range of two iterator ranges
"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 63
100M elements
double sum = 0;
for (const Point& v : range)
sum += v.x;
Performance?
Range Traverse time
std::vector 1.0
Joined range of two iterator ranges 1.18
"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 64
100M elements
double sum = 0;
for (const Point& v : range)
sum += v.x;
"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 65
 Мыслите в терминах алгоритмов
 Код должен ясно выражать намерение
 Знайте свои инструменты и используйте их к месту
// lambda functions (including generic)
// ternary operator
// exceptions
// transient parameters
std::next();
adjacent_find()
rotate()
is_partitioned()
partition_point()
// template parameters for iterators
// template parameters for predicates
// function return type deduction
boost::range
boost::algorithm
std::vector<T>::empty()
boost::make_iterator_range()
boost::join()
Спасибо за внимание!
Матросов Михаил
Технический менеджер, Align Technology
mmatrosov@aligntech.com
8 926 381-61-64

More Related Content

Similar to SECON'2017, Матросов Михаил. Matrosov, Повседневный С++: алгоритмы и интераторы

Используем неизменяемые данные и создаем качественный код — Игорь Кудрин, 2ГИС
Используем неизменяемые данные и создаем качественный код — Игорь Кудрин, 2ГИСИспользуем неизменяемые данные и создаем качественный код — Игорь Кудрин, 2ГИС
Используем неизменяемые данные и создаем качественный код — Игорь Кудрин, 2ГИС
2ГИС Технологии
 
Простые типы данных
Простые типы данныхПростые типы данных
Простые типы данных
alinabacalim
 
Опыт разработки статического анализатора кода
Опыт разработки статического анализатора кодаОпыт разработки статического анализатора кода
Опыт разработки статического анализатора кода
Andrey Karpov
 
Кодогенерация на службе оптимизации, Игорь Чевдарь, СКБ Контур
 Кодогенерация на службе оптимизации, Игорь Чевдарь, СКБ Контур  Кодогенерация на службе оптимизации, Игорь Чевдарь, СКБ Контур
Кодогенерация на службе оптимизации, Игорь Чевдарь, СКБ Контур
it-people
 
ИТМО Machine Learning. Рекомендательные системы — часть 1
ИТМО Machine Learning. Рекомендательные системы — часть 1ИТМО Machine Learning. Рекомендательные системы — часть 1
ИТМО Machine Learning. Рекомендательные системы — часть 1
Andrey Danilchenko
 
20100927 28 reqformalization-kuliamin
20100927 28 reqformalization-kuliamin20100927 28 reqformalization-kuliamin
20100927 28 reqformalization-kuliaminComputer Science Club
 

Similar to SECON'2017, Матросов Михаил. Matrosov, Повседневный С++: алгоритмы и интераторы (6)

Используем неизменяемые данные и создаем качественный код — Игорь Кудрин, 2ГИС
Используем неизменяемые данные и создаем качественный код — Игорь Кудрин, 2ГИСИспользуем неизменяемые данные и создаем качественный код — Игорь Кудрин, 2ГИС
Используем неизменяемые данные и создаем качественный код — Игорь Кудрин, 2ГИС
 
Простые типы данных
Простые типы данныхПростые типы данных
Простые типы данных
 
Опыт разработки статического анализатора кода
Опыт разработки статического анализатора кодаОпыт разработки статического анализатора кода
Опыт разработки статического анализатора кода
 
Кодогенерация на службе оптимизации, Игорь Чевдарь, СКБ Контур
 Кодогенерация на службе оптимизации, Игорь Чевдарь, СКБ Контур  Кодогенерация на службе оптимизации, Игорь Чевдарь, СКБ Контур
Кодогенерация на службе оптимизации, Игорь Чевдарь, СКБ Контур
 
ИТМО Machine Learning. Рекомендательные системы — часть 1
ИТМО Machine Learning. Рекомендательные системы — часть 1ИТМО Machine Learning. Рекомендательные системы — часть 1
ИТМО Machine Learning. Рекомендательные системы — часть 1
 
20100927 28 reqformalization-kuliamin
20100927 28 reqformalization-kuliamin20100927 28 reqformalization-kuliamin
20100927 28 reqformalization-kuliamin
 

More from SECON

SECON'2017, LAZADA Effartlrss Shopping, Как мы тестируем?
 SECON'2017, LAZADA Effartlrss Shopping, Как мы тестируем? SECON'2017, LAZADA Effartlrss Shopping, Как мы тестируем?
SECON'2017, LAZADA Effartlrss Shopping, Как мы тестируем?
SECON
 
SECON'2017, Куприенко Игорь, Университет 4.0: Ждать Нельзя Внедрять
SECON'2017, Куприенко Игорь, Университет 4.0: Ждать Нельзя ВнедрятьSECON'2017, Куприенко Игорь, Университет 4.0: Ждать Нельзя Внедрять
SECON'2017, Куприенко Игорь, Университет 4.0: Ждать Нельзя Внедрять
SECON
 
SECON'2017, Васильков Василий, Elm в production
SECON'2017, Васильков Василий, Elm в productionSECON'2017, Васильков Василий, Elm в production
SECON'2017, Васильков Василий, Elm в production
SECON
 
SECON'2017, Емельянов Игорь, Я хочу стать программистом: первые шаги.
SECON'2017, Емельянов Игорь, Я хочу стать программистом: первые шаги.SECON'2017, Емельянов Игорь, Я хочу стать программистом: первые шаги.
SECON'2017, Емельянов Игорь, Я хочу стать программистом: первые шаги.
SECON
 
SECON'2017, Тыкушин Анатолий, Болдырев Михаил, Расследование кибер-преступлений
SECON'2017, Тыкушин Анатолий, Болдырев Михаил, Расследование кибер-преступленийSECON'2017, Тыкушин Анатолий, Болдырев Михаил, Расследование кибер-преступлений
SECON'2017, Тыкушин Анатолий, Болдырев Михаил, Расследование кибер-преступлений
SECON
 
SECON'2017, Рожкова Надежда, Бухгалтерские лайфхаки для IT компаний
SECON'2017, 	Рожкова Надежда, Бухгалтерские лайфхаки для IT компанийSECON'2017, 	Рожкова Надежда, Бухгалтерские лайфхаки для IT компаний
SECON'2017, Рожкова Надежда, Бухгалтерские лайфхаки для IT компаний
SECON
 
SECON'2017, Янов Альберт, Управленческий учет в компании: для чего он нужен и...
SECON'2017, Янов Альберт, Управленческий учет в компании: для чего он нужен и...SECON'2017, Янов Альберт, Управленческий учет в компании: для чего он нужен и...
SECON'2017, Янов Альберт, Управленческий учет в компании: для чего он нужен и...
SECON
 
SECON'2017, Емелина Елена, Управленческий учет в софтверной компании на коленке
SECON'2017, Емелина Елена, Управленческий учет в софтверной компании на коленкеSECON'2017, Емелина Елена, Управленческий учет в софтверной компании на коленке
SECON'2017, Емелина Елена, Управленческий учет в софтверной компании на коленке
SECON
 
SECON'2017, Кузнецов Михаил, Самоуправляемая компания без бюрократии и фигни
SECON'2017, Кузнецов Михаил, Самоуправляемая компания без бюрократии и фигниSECON'2017, Кузнецов Михаил, Самоуправляемая компания без бюрократии и фигни
SECON'2017, Кузнецов Михаил, Самоуправляемая компания без бюрократии и фигни
SECON
 
SECON'2017, Коротков Анатолий, #noprojects #nomvp .. куда катится мир?
SECON'2017, Коротков Анатолий, #noprojects #nomvp .. куда катится мир?SECON'2017, Коротков Анатолий, #noprojects #nomvp .. куда катится мир?
SECON'2017, Коротков Анатолий, #noprojects #nomvp .. куда катится мир?
SECON
 
SECON'2017, Трошин Алексей, Выжить без менеджера: шаблоны правильных коммуник...
SECON'2017, Трошин Алексей, Выжить без менеджера: шаблоны правильных коммуник...SECON'2017, Трошин Алексей, Выжить без менеджера: шаблоны правильных коммуник...
SECON'2017, Трошин Алексей, Выжить без менеджера: шаблоны правильных коммуник...
SECON
 
SECON'2017, Цветцих Денис, Как добавить работе по Agile предсказуемости, не п...
SECON'2017, Цветцих Денис, Как добавить работе по Agile предсказуемости, не п...SECON'2017, Цветцих Денис, Как добавить работе по Agile предсказуемости, не п...
SECON'2017, Цветцих Денис, Как добавить работе по Agile предсказуемости, не п...
SECON
 
SECON'2017, Мартынов Антон, Опыт использования удаленных команд при реализаци...
SECON'2017, Мартынов Антон, Опыт использования удаленных команд при реализаци...SECON'2017, Мартынов Антон, Опыт использования удаленных команд при реализаци...
SECON'2017, Мартынов Антон, Опыт использования удаленных команд при реализаци...
SECON
 
SECON'2017, Цаль-Цалко Иван, Go на практике
SECON'2017, Цаль-Цалко Иван, Go на практикеSECON'2017, Цаль-Цалко Иван, Go на практике
SECON'2017, Цаль-Цалко Иван, Go на практике
SECON
 
SECON'2017, Неволин Роман, Функциональный C#
SECON'2017, Неволин Роман, Функциональный C#SECON'2017, Неволин Роман, Функциональный C#
SECON'2017, Неволин Роман, Функциональный C#
SECON
 
SECON'2017, Мелехова Анна, Архитектура как стихия. Обуздываем энтропию проекта
SECON'2017, Мелехова Анна, Архитектура как стихия. Обуздываем энтропию проектаSECON'2017, Мелехова Анна, Архитектура как стихия. Обуздываем энтропию проекта
SECON'2017, Мелехова Анна, Архитектура как стихия. Обуздываем энтропию проекта
SECON
 
SECON'2017, Макарычев Костантин, Использование Spark для машинного обучения
SECON'2017, Макарычев Костантин, Использование Spark для машинного обученияSECON'2017, Макарычев Костантин, Использование Spark для машинного обучения
SECON'2017, Макарычев Костантин, Использование Spark для машинного обучения
SECON
 
SECON'2017, Журавлев Денис, Маркетинг без маркетолога
SECON'2017, Журавлев Денис, Маркетинг без маркетологаSECON'2017, Журавлев Денис, Маркетинг без маркетолога
SECON'2017, Журавлев Денис, Маркетинг без маркетолога
SECON
 
SECON'2017, Шатров Михаил, Инструменты успешного предпринимателя
SECON'2017, Шатров Михаил, Инструменты успешного предпринимателяSECON'2017, Шатров Михаил, Инструменты успешного предпринимателя
SECON'2017, Шатров Михаил, Инструменты успешного предпринимателя
SECON
 
SECON'2017, Цымбал Дмитрий, Компания - Компания. Дружба на этом уровне.
SECON'2017, Цымбал Дмитрий, Компания - Компания. Дружба на этом уровне.SECON'2017, Цымбал Дмитрий, Компания - Компания. Дружба на этом уровне.
SECON'2017, Цымбал Дмитрий, Компания - Компания. Дружба на этом уровне.
SECON
 

More from SECON (20)

SECON'2017, LAZADA Effartlrss Shopping, Как мы тестируем?
 SECON'2017, LAZADA Effartlrss Shopping, Как мы тестируем? SECON'2017, LAZADA Effartlrss Shopping, Как мы тестируем?
SECON'2017, LAZADA Effartlrss Shopping, Как мы тестируем?
 
SECON'2017, Куприенко Игорь, Университет 4.0: Ждать Нельзя Внедрять
SECON'2017, Куприенко Игорь, Университет 4.0: Ждать Нельзя ВнедрятьSECON'2017, Куприенко Игорь, Университет 4.0: Ждать Нельзя Внедрять
SECON'2017, Куприенко Игорь, Университет 4.0: Ждать Нельзя Внедрять
 
SECON'2017, Васильков Василий, Elm в production
SECON'2017, Васильков Василий, Elm в productionSECON'2017, Васильков Василий, Elm в production
SECON'2017, Васильков Василий, Elm в production
 
SECON'2017, Емельянов Игорь, Я хочу стать программистом: первые шаги.
SECON'2017, Емельянов Игорь, Я хочу стать программистом: первые шаги.SECON'2017, Емельянов Игорь, Я хочу стать программистом: первые шаги.
SECON'2017, Емельянов Игорь, Я хочу стать программистом: первые шаги.
 
SECON'2017, Тыкушин Анатолий, Болдырев Михаил, Расследование кибер-преступлений
SECON'2017, Тыкушин Анатолий, Болдырев Михаил, Расследование кибер-преступленийSECON'2017, Тыкушин Анатолий, Болдырев Михаил, Расследование кибер-преступлений
SECON'2017, Тыкушин Анатолий, Болдырев Михаил, Расследование кибер-преступлений
 
SECON'2017, Рожкова Надежда, Бухгалтерские лайфхаки для IT компаний
SECON'2017, 	Рожкова Надежда, Бухгалтерские лайфхаки для IT компанийSECON'2017, 	Рожкова Надежда, Бухгалтерские лайфхаки для IT компаний
SECON'2017, Рожкова Надежда, Бухгалтерские лайфхаки для IT компаний
 
SECON'2017, Янов Альберт, Управленческий учет в компании: для чего он нужен и...
SECON'2017, Янов Альберт, Управленческий учет в компании: для чего он нужен и...SECON'2017, Янов Альберт, Управленческий учет в компании: для чего он нужен и...
SECON'2017, Янов Альберт, Управленческий учет в компании: для чего он нужен и...
 
SECON'2017, Емелина Елена, Управленческий учет в софтверной компании на коленке
SECON'2017, Емелина Елена, Управленческий учет в софтверной компании на коленкеSECON'2017, Емелина Елена, Управленческий учет в софтверной компании на коленке
SECON'2017, Емелина Елена, Управленческий учет в софтверной компании на коленке
 
SECON'2017, Кузнецов Михаил, Самоуправляемая компания без бюрократии и фигни
SECON'2017, Кузнецов Михаил, Самоуправляемая компания без бюрократии и фигниSECON'2017, Кузнецов Михаил, Самоуправляемая компания без бюрократии и фигни
SECON'2017, Кузнецов Михаил, Самоуправляемая компания без бюрократии и фигни
 
SECON'2017, Коротков Анатолий, #noprojects #nomvp .. куда катится мир?
SECON'2017, Коротков Анатолий, #noprojects #nomvp .. куда катится мир?SECON'2017, Коротков Анатолий, #noprojects #nomvp .. куда катится мир?
SECON'2017, Коротков Анатолий, #noprojects #nomvp .. куда катится мир?
 
SECON'2017, Трошин Алексей, Выжить без менеджера: шаблоны правильных коммуник...
SECON'2017, Трошин Алексей, Выжить без менеджера: шаблоны правильных коммуник...SECON'2017, Трошин Алексей, Выжить без менеджера: шаблоны правильных коммуник...
SECON'2017, Трошин Алексей, Выжить без менеджера: шаблоны правильных коммуник...
 
SECON'2017, Цветцих Денис, Как добавить работе по Agile предсказуемости, не п...
SECON'2017, Цветцих Денис, Как добавить работе по Agile предсказуемости, не п...SECON'2017, Цветцих Денис, Как добавить работе по Agile предсказуемости, не п...
SECON'2017, Цветцих Денис, Как добавить работе по Agile предсказуемости, не п...
 
SECON'2017, Мартынов Антон, Опыт использования удаленных команд при реализаци...
SECON'2017, Мартынов Антон, Опыт использования удаленных команд при реализаци...SECON'2017, Мартынов Антон, Опыт использования удаленных команд при реализаци...
SECON'2017, Мартынов Антон, Опыт использования удаленных команд при реализаци...
 
SECON'2017, Цаль-Цалко Иван, Go на практике
SECON'2017, Цаль-Цалко Иван, Go на практикеSECON'2017, Цаль-Цалко Иван, Go на практике
SECON'2017, Цаль-Цалко Иван, Go на практике
 
SECON'2017, Неволин Роман, Функциональный C#
SECON'2017, Неволин Роман, Функциональный C#SECON'2017, Неволин Роман, Функциональный C#
SECON'2017, Неволин Роман, Функциональный C#
 
SECON'2017, Мелехова Анна, Архитектура как стихия. Обуздываем энтропию проекта
SECON'2017, Мелехова Анна, Архитектура как стихия. Обуздываем энтропию проектаSECON'2017, Мелехова Анна, Архитектура как стихия. Обуздываем энтропию проекта
SECON'2017, Мелехова Анна, Архитектура как стихия. Обуздываем энтропию проекта
 
SECON'2017, Макарычев Костантин, Использование Spark для машинного обучения
SECON'2017, Макарычев Костантин, Использование Spark для машинного обученияSECON'2017, Макарычев Костантин, Использование Spark для машинного обучения
SECON'2017, Макарычев Костантин, Использование Spark для машинного обучения
 
SECON'2017, Журавлев Денис, Маркетинг без маркетолога
SECON'2017, Журавлев Денис, Маркетинг без маркетологаSECON'2017, Журавлев Денис, Маркетинг без маркетолога
SECON'2017, Журавлев Денис, Маркетинг без маркетолога
 
SECON'2017, Шатров Михаил, Инструменты успешного предпринимателя
SECON'2017, Шатров Михаил, Инструменты успешного предпринимателяSECON'2017, Шатров Михаил, Инструменты успешного предпринимателя
SECON'2017, Шатров Михаил, Инструменты успешного предпринимателя
 
SECON'2017, Цымбал Дмитрий, Компания - Компания. Дружба на этом уровне.
SECON'2017, Цымбал Дмитрий, Компания - Компания. Дружба на этом уровне.SECON'2017, Цымбал Дмитрий, Компания - Компания. Дружба на этом уровне.
SECON'2017, Цымбал Дмитрий, Компания - Компания. Дружба на этом уровне.
 

SECON'2017, Матросов Михаил. Matrosov, Повседневный С++: алгоритмы и интераторы

  • 1. #SECONRU Повседневный С++: алгоритмы и итераторы Матросов Михаил Технический менеджер, Align Technology Москва
  • 2. "Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 2
  • 3. "Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 33 С++17 С++11/14 С++98 С High level Expert level Modern C++ Almost the same :(
  • 4. “Within C++ is a smaller, simpler, safer language struggling to get out” Bjarne Stroustrup "Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 4
  • 5. High level:  Парадигма RAII и исключения (exceptions)  Семантика перемещения  λ-функции  Классы и конструкторы  Простые шаблоны  STL  Утилиты и алгоритмы boost "Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 5 Expert level:  Операторы new/delete, владеющие указатели  Пользовательские операции копирования и перемещения  Пользовательские деструкторы  Закрытое, защищённое, ромбовидное, виртуальное наследование  Шаблонная магия  Все функции языка Си, препроцессор  «Голые» циклы
  • 7. План действий  Рассмотрим пример реального кода  Вместе выполним рефакторинг  Перепишем с нуля  Обобщим решение "Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 7
  • 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) 8
  • 9. "Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 9 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); }); middle = middle != points.end() ? std::next(middle) : points.begin(); rotate(points, middle); if (!is_partitioned(points, isRight)) throw std::runtime_error("Unexpected order"); points.erase(partition_point(points, isRight), points.end()); return points; }
  • 10. "Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 10 const std::vector<Point> extract(const std::vector<Point>& points) {
  • 11. "Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 11 std::vector<Point> extract(const std::vector<Point>& points) {
  • 12. "Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 12 std::vector<Point> extract(const std::vector<Point>& points) { std::vector<Point> result; result.clear();
  • 13. "Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 13 std::vector<Point> extract(const std::vector<Point>& points) { std::vector<Point> result;
  • 14. "Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 14 std::vector<Point> extract(const std::vector<Point>& points) { std::vector<Point> result; if (points.size() == 0) return result;
  • 15. "Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 15 std::vector<Point> extract(const std::vector<Point>& points) { std::vector<Point> result; if (points.empty()) return result;
  • 16. "Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 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; }
  • 17. "Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 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; }
  • 18. "Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 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; }
  • 19. "Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 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; }
  • 20. "Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 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);
  • 21. "Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 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);
  • 22. "Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 22 int p = findBoundary(false); int q = findBoundary(true); if (p == q) { if (isRight(*points.begin())) return points; else return result; }
  • 23. "Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 23 int p = findBoundary(false); int q = findBoundary(true); if (p == q) { if (isRight(points[0])) return points; else return result; }
  • 24. "Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 24 int p = findBoundary(false); int q = findBoundary(true); if (p == q) return isRight(points[0]) ? points : result;
  • 25. "Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 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; }
  • 26. "Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 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
  • 27. "Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 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; }
  • 28. "Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 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; }
  • 29. "Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 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);
  • 30. "Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 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);
  • 31. "Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 31 appendResult(p, q, true); appendResult(q, p, false); return std::move(result); }
  • 32. "Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 32 appendResult(p, q, true); appendResult(q, p, false); return result; }
  • 33. "Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 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);
  • 34. "Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 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
  • 35. "Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 35 0 1 2 3 4 5 6 1. Найти первый элемент 2. Сдвинуть его в началоp
  • 36. "Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 36 6 0 1 2 3 4 5 1. Найти первый элемент 2. Сдвинуть его в начало
  • 37. "Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 37 5 6 0 1 2 3 4 1. Найти первый элемент 2. Сдвинуть его в начало
  • 38. "Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 38 5 6 0 1 2 34 1. Найти первый элемент 2. Сдвинуть его в начало 3. Проверить структуру 4. Выкинуть хвост 5. Вернуть что осталось
  • 39. std::vector<Point> extractRight(std::vector<Point> points) { "Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 39 0 1 2 3 4 5 6
  • 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; }; "Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 40 0 1 2 3 4 5 6
  • 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); }); middle = middle != points.end() ? std::next(middle) : points.begin(); "Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 41 0 1 2 3 4 5 6 middle
  • 42. 42 5 6 0 1 2 34 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); }); middle = middle != points.end() ? std::next(middle) : points.begin(); rotate(points, middle); "Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017
  • 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); }); middle = middle != points.end() ? std::next(middle) : points.begin(); rotate(points, middle); if (!is_partitioned(points, isRight)) throw std::runtime_error("Unexpected order"); "Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 43 5 6 0 1 2 34
  • 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); }); middle = middle != points.end() ? std::next(middle) : points.begin(); rotate(points, middle); if (!is_partitioned(points, isRight)) throw std::runtime_error("Unexpected order"); points.erase(partition_point(points, isRight), points.end()); "Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 44 5 6 0 14
  • 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); }); middle = middle != points.end() ? std::next(middle) : points.begin(); rotate(points, middle); if (!is_partitioned(points, isRight)) throw std::runtime_error("Unexpected order"); points.erase(partition_point(points, isRight), points.end()); return points; } "Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 45 5 6 0 14
  • 46. "Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 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; }
  • 47. "Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 47 // Two specialized overloads std::vector<Point> extractRight(std::vector<Point>&& points) { // Process points in-place... return points; } std::vector<Point> extractRight(const std::vector<Point>& points) { std::vector<Point> result = points; // Might be altered! // Process result... return result; } // One universal function std::vector<Point> extractRight(std::vector<Point> points) { // Process points in-place... return points; }
  • 48. "Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 48 0 1 2 3 middlefirst last 4 5 6
  • 49. "Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 49 Sean Parent: C++ Seasoning (no raw loops)
  • 50. "Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 50
  • 51. "Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 51
  • 52. Обобщаем!  std::vector → последовательность (пара итераторов)  isRight() → предикат  Результат как копия → результат как подпоследовательность "Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 52
  • 53. "Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 53 0 1 2 3 4 5 6 Раз……два!
  • 54. "Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 54 template<class It, class Predicate> auto extractIf(It first, It last, Predicate p) { 0 1 2 3 4 5 6 first last
  • 55. "Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 55 template<class It, class Predicate> auto extractIf(It first, It last, Predicate p) { using namespace boost::range; using namespace boost::algorithm; 0 1 2 3 4 5 6 first last
  • 56. "Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 56 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; 0 1 2 3 4 5 6 first lastmiddle
  • 57. "Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 57 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)); 0 1 2 3 4 5 6 first lastmiddle
  • 58. "Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 58 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"); 0 1 2 3 4 5 6 first lastmiddle
  • 59. "Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 59 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); 0 1 2 3 4 5 6 first lastmiddleend
  • 60. "Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 60 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); } 0 1 2 3 4 5 6 first lastmiddleend
  • 61. "Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 61 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); } 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); }); middle = middle != points.end() ? std::next(middle) : points.begin(); rotate(points, middle); if (!is_partitioned(points, isRight)) throw std::runtime_error("Unexpected order"); points.erase( partition_point(points, isRight), points.end()); return points; }
  • 62.  Ответь на вопрос  Получи мячик  …  PROFIT! "Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 62
  • 63. Performance? Range Traverse time std::vector 1.0 Joined range of two iterator ranges "Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 63 100M elements double sum = 0; for (const Point& v : range) sum += v.x;
  • 64. Performance? Range Traverse time std::vector 1.0 Joined range of two iterator ranges 1.18 "Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 64 100M elements double sum = 0; for (const Point& v : range) sum += v.x;
  • 65. "Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 65  Мыслите в терминах алгоритмов  Код должен ясно выражать намерение  Знайте свои инструменты и используйте их к месту // lambda functions (including generic) // ternary operator // exceptions // transient parameters std::next(); adjacent_find() rotate() is_partitioned() partition_point() // template parameters for iterators // template parameters for predicates // function return type deduction boost::range boost::algorithm std::vector<T>::empty() boost::make_iterator_range() boost::join() Спасибо за внимание!
  • 66. Матросов Михаил Технический менеджер, Align Technology mmatrosov@aligntech.com 8 926 381-61-64

Editor's Notes

  1. Разрабатываю на С++ в течение 12 лет, занимался обработкой изображений и 3D графикой. В настоящий момент технический менеджер в компании Align Technology. Это международная компания, производитель медицинского оборудования для нужд ортодонтии. Использует ПО, разработанное на С++. Я занимаюсь развитием платформы 3D CAD приложения для планирования ортодонтического лечения. Пытаюсь облегчить жизнь разработчиков, которые ей пользуются.
  2. По поводу фичей, взятых из boost: http://stackoverflow.com/q/8851670/261217
  3. 1. Самое важное, что появилось в С++11 и пришло оно из boost?
  4. Исходный текст функции.
  5. 1. No reason to return container by const value
  6. 1. No reason to clear container after it is default constructed
  7. 1. Use empty()
  8. found не нужен, т.к. мы можем его вывести через i
  9. Logic is duplicated
  10. Logic is duplicated
  11. Bad names
  12. How [0] and front() are different?
  13. Side effects of sqrt(-1)?
  14. Why do we need NAN when we have std::numeric_limits<float>::quiet_NaN()? How returning braced list might be worse than clear and return existing vector? (NRVO) ToDo: check this.
  15. Similar code snippets most probably serve similar purpose, and thus needs to be represented by a single entity.
  16. What other alternatives do we have to represent an error?
  17. RVO is disabled because standard says that type of returned value and return type of function should be the same.
  18. Algorithm to find first element - adjacent_find(). adjacent_find() returns iterator to the first element in the pair, how to retrieve the second? How is std::next() better than it+1? How is different from ++it?
  19. 1. Algorithm to move it to beginning – rotate()
  20. Algorithm to check structure – is_partitioned() Algorithm to detect the tail – partition_point()
  21. 1. In which scenario this signature is preferable?
  22. Why do we need & in []? What exactly this lambda function correspond to?
  23. ToDo: можно ли оптимально?
  24. Passing arguments by value.
  25. Measured with Visual Studio 2017, x64
  26. Additional questions for winners: Что возвращает rotate()? Безопасно ли объединять два временных диапазона? Как проще всего присвоить какое-либо значение N элементам в конце массива?