C++17 STL Стандартная библиотека шаблонов - Яцек Галовиц

C++17 STL Стандартная библиотека шаблонов читать книгу онлайн
С++ — объектно-ориентированный язык программирования, без которого сегодня немыслима промышленная разработка ПО. В этой замечательной книге описана работа с контейнерами, алгоритмами, вспомогательными классами, лямбда-выражениями и другими интересными инструментами, которыми богат современный С++. Освоив материал, вы сможете коренным образом пересмотреть привычный подход к программированию.
Преимущество издания — в подробном описании стандартной библиотеки шаблонов С++, STL. Ее свежая версия была выпущена в 2017 году. В книге вы найдете более 90 максимально реалистичных примеров, которые демонстрируют всю мощь STL. Многие из них станут базовыми кирпичиками для решения более универсальных задач.
Вооружившись этой книгой, вы сможете эффективно использовать С++17 для создания высококачественного и высокопроизводительного ПО, применимого в различных отраслях.
Это может показаться непонятным, так что рассмотрим пример: команда ratio_multiply<ratio<2, 3>, ratio<4, 5>> даст результат ratio<8, 15>, поскольку (2/3) * (4/5) = 8/15.
Полученные описания типов эквивалентны следующим описаниям:
using seconds = chrono::duration<double, ratio<1, 1>>;
using milliseconds = chrono::duration<double, ratio<1, 1000>>;
using microseconds = chrono::duration<double, ratio<1, 1000000>>;
После получения этих типов можно легко выполнять преобразования между ними. При наличии промежутка времени d с типом seconds можно преобразовать его в тип milliseconds, передав в конструктор другого типа — milliseconds(d).
Дополнительная информация
В других учебниках и книгах при преобразовании промежутков времени вы могли столкнуться с duration_cast. Если у нас есть промежуток времени типа chrono::milliseconds и нужно преобразовать его к типу chrono::hours, например, то следует написать конструкцию duration_cast<chrono::hours>(milliseconds_value), поскольку данные единицы измерения зависят от целочисленных типов. Преобразование точных единиц времени в менее точные приводит к потере точности, именно поэтому и нужен duration_cast. Для продолжительностей, основанных на типах double или float, этого не требуется.
Выполняем преобразование между абсолютными и относительными значениями с использованием std::chrono
До C++11 было довольно сложно получить физическое время и просто вывести его на экран, поскольку C++ не имела собственной библиотеки для работы с временем. Требовалось всегда вызывать функции библиотеки С, которая выглядит очень архаично, учитывая, что такие вызовы могут быть инкапсулированы в собственные классы.
Начиная с C++11, в STL можно найти библиотеку chrono, она значительно упрощает решение задач, связанных с временем.
В этом примере мы возьмем местное время, выведем его на экран и поработаем с ним, добавляя разные смещения, что очень удобно делать с помощью библиотеки std::chrono.
Как это делается
В примере мы сохраним текущее время и выведем его на экран. Кроме того, наша программа будет добавлять разные смещения к сохраненному времени и выводить на экран полученные результаты.
1. Сначала идут типичные директивы include, затем мы объявляем об использовании по умолчанию пространства имен std:
#include <iostream>
#include <iomanip>
#include <chrono>
using namespace std;
2. Выведем на экран абсолютные моменты времени. Они будут иметь форму шаблона типа chrono::time_point, поэтому просто перегрузим для него оператор выходного потока. Существуют разные способы вывести на экран дату и/или время для заданного момента. Мы применим только стандартное форматирование %c. Можно было бы, конечно, также вывести только время, только дату, только год или что-то еще, приходящее на ум. Все преобразования между разными типами до того, как мы сможем использовать put_time, будут выглядеть несколько «неаккуратно», но мы провернем это лишь однажды.
ostream& operator<<(ostream &os,
const chrono::time_point<chrono::system_clock> &t)
{
const auto tt (chrono::system_clock::to_time_t(t));
const auto loct (std::localtime(&tt));
return os << put_time(loct, "%c");
}
3. Для секунд, минут, часов и т.д. в STL существуют описания типов. Сейчас мы добавим тип days. Это делается легко; нужно лишь специализировать шаблон chrono::duration, сославшись на часы и умножив их на 24, поскольку сутки насчитывают 24 часа.
using days = chrono::duration<
chrono::hours::rep,
ratio_multiply<chrono::hours::period, ratio<24>>>;
4. Чтобы наиболее элегантным способом выразить продолжительность длиной в несколько дней, можно определить собственный пользовательский литерал days. Теперь можно написать 3_days, чтобы создать значение, которое представляет собой три дня.
constexpr days operator ""_days(unsigned long long h)
{
return days{h};
}
5. В самой программе сделаем снимок момента времени, который затем просто выведем на экран. Это очень легко и удобно, поскольку мы уже реализовали правильную версию перегруженного оператора.
int main()
{
auto now (chrono::system_clock::now());
cout << "The current date and time is " << now << 'n';
6. Сохранив текущее время в переменной now, можем добавить к нему произвольные продолжительности и также вывести их на экран. Добавим к текущему времени 12 часов и выведем результат на экран:
chrono::hours chrono_12h {12};
cout << "In 12 hours, it will be "
<< (now + chrono_12h)<< 'n';
7. Объявляя об использовании по умолчанию пространства имен chrono_literals, разблокируем все существующие литералы, описывающие продолжительность, для часов, секунд и т.д. Таким образом, можно изящно вывести на экран, какое время было 12 часов 15 минут назад или семь дней назад.
using namespace chrono_literals;
cout << "12 hours and 15 minutes ago, it was "
<< (now - 12h - 15min) << 'n'
<< "1 week ago, it was "
<< (now - 7_days) << 'n';
}
8. Компиляция и запуск программы дадут следующий результат. Поскольку мы использовали в качестве строки форматирования %c, получим довольно полное описание в конкретном формате. Поработав с разными строками формата, можем вывести время в любом формате, который нам нравится. Обратите внимание: здесь мы применяем 24-часовой формат.
$ ./relative_absolute_times
The current date and time is Fri May 5 13:20:38 2017
In 12 hours, it will be Sat May 6 01:20:38 2017
12 hours and 15 minutes ago, it was Fri May 5 01:05:38 2017
1 week ago, it was Fri Apr 28 13:20:38 2017
Как это работает
Мы получили текущий момент времени из std::chrono::system_clock. Этот класс часов STL единственный способен преобразовывать свои значения моментов времени в структуру time, которая может быть отображена в виде понятной человеку строки описания.
Чтобы вывести на экран такие моменты времени, мы реализовали оператор << для потока вывода:
ostream& operator<<(ostream &os,
const chrono::time_point<chrono::system_clock> &t)
{
const auto tt (chrono::system_clock::to_time_t(t));
const auto loct (std::localtime(&tt));
return os << put_time(loct, "%c");
}