Повседневный С++: алгоритмы и итераторы corehard_by
Я рассмотрю ряд простых прикладных задач и покажу, как их можно эффективно и элегантно решить с помощью стандартных средств современного С++. Доклад включает работу с залом: участники будут предлагать свои улучшения для конкретных примеров кода, а также отвечать на поставленные вопросы (например, найти ошибку в приведённом примере). Доклад рассчитан на базовые знания языка.
Михаил Матросов
Технический менеджер @Align Technology, Москва
Основы С++ (массивы, указатели). Задачи с массивамиOlga Maksimenkova
Расширенная версия презентации со школы учителей 2016. Изменён порядок материала, добавлены сортировки и индексация, слайды Незнанова А.А. и слайды с задачами.
CSSO – инструмент для минификации CSS, который не так давно вернулся к активной разработке. Помимо исправленных багов и новых фич, он значительно ускорился и стал одним из самых быстрых структурных минификаторов CSS.
Доклад о том как это достигалось, оптимизациях, деоптимизациях, структурах данных и подходах.
Holy.js, Санкт-Петербург, 5 июня 2016
Видео: https://www.youtube.com/watch?v=8o3gKKD_J4A
Статический анализ: вокруг Java за 60 минутAndrey Karpov
Статический анализ всё больше воспринимается как неотъемлемая часть процесса разработки качественного программного обеспечения. Разумеется, у этой технологии уже есть свои сторонники и противники, но, несмотря на это, тема статического анализа всё более актуальна и требует детального рассмотрения. Рассмотрим, что такое статический анализ, как он применяется и как влияет на качество и надёжность кода. Поговорим о важности раннего обнаружения ошибок и дефектов уязвимости. Рассмотрим существующие инструменты для Java, такие как Sonar Java, FindBugs и анализатор встроенном в среду разработки IntelliJ IDEA. Расскажем историю, почему несмотря на уже существующие инструменты, мы решили разработать PVS-Studio для Java, как мы это делали и что в итоге получилось. В конце затронем вопрос интеграции статических анализаторов кода в большие старые проекты. Другими словами, как увидеть 100500 срабатываний и не упасть духом.
Повседневный С++: алгоритмы и итераторы corehard_by
Я рассмотрю ряд простых прикладных задач и покажу, как их можно эффективно и элегантно решить с помощью стандартных средств современного С++. Доклад включает работу с залом: участники будут предлагать свои улучшения для конкретных примеров кода, а также отвечать на поставленные вопросы (например, найти ошибку в приведённом примере). Доклад рассчитан на базовые знания языка.
Михаил Матросов
Технический менеджер @Align Technology, Москва
Основы С++ (массивы, указатели). Задачи с массивамиOlga Maksimenkova
Расширенная версия презентации со школы учителей 2016. Изменён порядок материала, добавлены сортировки и индексация, слайды Незнанова А.А. и слайды с задачами.
CSSO – инструмент для минификации CSS, который не так давно вернулся к активной разработке. Помимо исправленных багов и новых фич, он значительно ускорился и стал одним из самых быстрых структурных минификаторов CSS.
Доклад о том как это достигалось, оптимизациях, деоптимизациях, структурах данных и подходах.
Holy.js, Санкт-Петербург, 5 июня 2016
Видео: https://www.youtube.com/watch?v=8o3gKKD_J4A
Статический анализ: вокруг Java за 60 минутAndrey Karpov
Статический анализ всё больше воспринимается как неотъемлемая часть процесса разработки качественного программного обеспечения. Разумеется, у этой технологии уже есть свои сторонники и противники, но, несмотря на это, тема статического анализа всё более актуальна и требует детального рассмотрения. Рассмотрим, что такое статический анализ, как он применяется и как влияет на качество и надёжность кода. Поговорим о важности раннего обнаружения ошибок и дефектов уязвимости. Рассмотрим существующие инструменты для Java, такие как Sonar Java, FindBugs и анализатор встроенном в среду разработки IntelliJ IDEA. Расскажем историю, почему несмотря на уже существующие инструменты, мы решили разработать PVS-Studio для Java, как мы это делали и что в итоге получилось. В конце затронем вопрос интеграции статических анализаторов кода в большие старые проекты. Другими словами, как увидеть 100500 срабатываний и не упасть духом.
Опыт разработки статического анализатора кодаAndrey Karpov
Один из основателей проекта PVS-Studio расскажет об опыте разработки статического анализатора кода C++. У инструментов статического анализа кода существует "проблема айсберга". От пользователей скрыты сложные механизмы анализа кода, и иногда им кажется, что статические анализаторы – это просто какие-то утилиты, ищущие опечатки с помощью регулярных выражений. Автор доклада постарается в общих чертах описать, как всё обстоит на самом деле. Он покажет на примерах, почему нормальный анализ с помощью регулярных выражений нереализуем, что такое Data Flow анализ, а также расскажет о других технологиях, применяемых при анализе кода. Вкратце будет затронут вопрос использования нейронных сетей, обсуждение которых сейчас является очень модной темой, и рассказано, почему с точки зрения анализа кода отношение к этому направлению является очень скептическим.
ИТМО Machine Learning. Рекомендательные системы — часть 1Andrey Danilchenko
Лекция-введение в рекомендательные системы в рамках курса по машинному обучению для студентов четвертого курса на кафедре КТ ИТМО. Часть 1 — kNN, SVD, iALS.
SECON'2017, LAZADA Effartlrss Shopping, Как мы тестируем?SECON
Тестирование заказов в ecommerce международного масштаба/ Order Lifecycle - Жизненный цикл заказа vs QA / Lazada. Азиатская кухня ecommerce тестирования.
Опыт разработки статического анализатора кодаAndrey Karpov
Один из основателей проекта PVS-Studio расскажет об опыте разработки статического анализатора кода C++. У инструментов статического анализа кода существует "проблема айсберга". От пользователей скрыты сложные механизмы анализа кода, и иногда им кажется, что статические анализаторы – это просто какие-то утилиты, ищущие опечатки с помощью регулярных выражений. Автор доклада постарается в общих чертах описать, как всё обстоит на самом деле. Он покажет на примерах, почему нормальный анализ с помощью регулярных выражений нереализуем, что такое Data Flow анализ, а также расскажет о других технологиях, применяемых при анализе кода. Вкратце будет затронут вопрос использования нейронных сетей, обсуждение которых сейчас является очень модной темой, и рассказано, почему с точки зрения анализа кода отношение к этому направлению является очень скептическим.
ИТМО Machine Learning. Рекомендательные системы — часть 1Andrey Danilchenko
Лекция-введение в рекомендательные системы в рамках курса по машинному обучению для студентов четвертого курса на кафедре КТ ИТМО. Часть 1 — kNN, SVD, iALS.
SECON'2017, LAZADA Effartlrss Shopping, Как мы тестируем?SECON
Тестирование заказов в ecommerce международного масштаба/ Order Lifecycle - Жизненный цикл заказа vs QA / Lazada. Азиатская кухня ecommerce тестирования.
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);
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. Вернуть что осталось
52. Обобщаем!
std::vector → последовательность (пара итераторов)
isRight() → предикат
Результат как копия → результат как подпоследовательность
"Повседневный С++: алгоритмы и итераторы", Михаил Матросов, Конференция SECON'2017 52
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()
Спасибо за внимание!
Разрабатываю на С++ в течение 12 лет, занимался обработкой изображений и 3D графикой. В настоящий момент технический менеджер в компании Align Technology. Это международная компания, производитель медицинского оборудования для нужд ортодонтии. Использует ПО, разработанное на С++. Я занимаюсь развитием платформы 3D CAD приложения для планирования ортодонтического лечения. Пытаюсь облегчить жизнь разработчиков, которые ей пользуются.
По поводу фичей, взятых из boost: http://stackoverflow.com/q/8851670/261217
1. Самое важное, что появилось в С++11 и пришло оно из boost?
Исходный текст функции.
1. No reason to return container by const value
1. No reason to clear container after it is default constructed
1. Use empty()
found не нужен, т.к. мы можем его вывести через i
Logic is duplicated
Logic is duplicated
Bad names
How [0] and front() are different?
Side effects of sqrt(-1)?
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.
Similar code snippets most probably serve similar purpose, and thus needs to be represented by a single entity.
What other alternatives do we have to represent an error?
RVO is disabled because standard says that type of returned value and return type of function should be the same.
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?
1. Algorithm to move it to beginning – rotate()
Algorithm to check structure – is_partitioned()
Algorithm to detect the tail – partition_point()
1. In which scenario this signature is preferable?
Why do we need & in []?
What exactly this lambda function correspond to?
ToDo: можно ли оптимально?
Passing arguments by value.
Measured with Visual Studio 2017, x64
Additional questions for winners:
Что возвращает rotate()?
Безопасно ли объединять два временных диапазона?
Как проще всего присвоить какое-либо значение N элементам в конце массива?