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

				
			C++17 STL Стандартная библиотека шаблонов читать книгу онлайн
С++ — объектно-ориентированный язык программирования, без которого сегодня немыслима промышленная разработка ПО. В этой замечательной книге описана работа с контейнерами, алгоритмами, вспомогательными классами, лямбда-выражениями и другими интересными инструментами, которыми богат современный С++. Освоив материал, вы сможете коренным образом пересмотреть привычный подход к программированию.
    Преимущество издания — в подробном описании стандартной библиотеки шаблонов С++, STL. Ее свежая версия была выпущена в 2017 году. В книге вы найдете более 90 максимально реалистичных примеров, которые демонстрируют всю мощь STL. Многие из них станут базовыми кирпичиками для решения более универсальных задач.
    Вооружившись этой книгой, вы сможете эффективно использовать С++17 для создания высококачественного и высокопроизводительного ПО, применимого в различных отраслях.
static pair<string, seconds> get_input()
{
string s;
6. Нужно получить время, в которое пользователь начал вводить строку, а также время, в которое он это делать закончил. Данная операция выглядит следующим образом:
const auto tic (chrono::steady_clock::now());
7. Сейчас мы получим данные от пользователя. Если эта операция пройдет безуспешно, то просто вернем кортеж, инициализированный значениями по умолчанию. Вызывающая сторона получит пустую строку:
if (!(cin >> s)) {
return {{}, {}};
}
8. В случае успеха продолжим работу, сделав еще один снимок текущего времени. Далее вернем входную строку и разницу между временными точками. Обратите внимание: обе временные точки выражены в абсолютном виде, но, вычислив их разность, мы получаем длительность:
const auto toc (chrono::steady_clock::now());
return {s, toc - tic};
}
9. Теперь реализуем саму программу. Запустим цикл, который будет работать до тех пор, пока пользователь не введет корректную строку. На каждом шаге цикла мы просим пользователя ввести строку "C++17", а затем вызываем функцию get_input:
int main()
{
while (true) {
cout << "Please type the word "C++17" as"
" fast as you can.n> ";
const auto [user_input, diff] = get_input();
10. Далее проверим входные данные. Если они пусты, то интерпретируем это как запрос на завершение программы:
if (user_input == "") { break; }
11. Если пользователь корректно введет строку "C++17", то поздравим его, а затем выведем время, которое ему потребовалось на данное действие. Метод diff.count() возвращает количество секунд в качестве числа с плавающей точкой. Используй мы оригинальный тип duration STL seconds, получили бы округленное целочисленное значение, а не дробное. Передавая конструктору milliseconds или microseconds нашу переменную diff перед вызовом count(), получаем то же значение, преобразованное в другую единицу измерения:
if (user_input == "C++17") {
cout << "Bravo. You did it in:n"
<< fixed << setprecision(2)
<< setw(12) << diff.count()
<< " seconds.n"
<< setw(12) << milliseconds(diff).count()
<< " milliseconds.n"
<< setw(12) << microseconds(diff).count()
<< " microseconds.n";
break;
12. Если пользователь сделал опечатку, то позволим ему повторить попытку:
} else {
cout << "Sorry, your input does not match."
" You may try again.n";
}
}
}
13. Компиляция и запуск программы дадут следующий результат. Сначала при наличии опечаток программа попросит пользователя ввести корректное слово. После этого она отобразит время, которое потребовалось на то, чтобы ввести его, в трех единицах измерения.
$ ./ratio_conversion
Please type the word "C++17" as fast as you can.
> c+17
Sorry, your input does not match. You may try again.
Please type the word "C++17" as fast as you can.
> C++17
Bravo. You did it in:
1.48 seconds.
1480.10 milliseconds.
1480099.00 microseconds.
Как это работает
Несмотря на то что этот раздел посвящен выполнению преобразований между разными единицами измерения времени, сначала нужно выбрать один из трех доступных объектов часов. Как правило, в пространстве имен std::chrono можно выбрать между system_clock, steady_clock и high_resolution_clock. Чем они отличаются? Взглянем на их описание (табл. 8.1).
Поскольку мы определяли продолжительность промежутка времени между двумя абсолютными точками во времени (они хранятся в переменных tic и toc), нам не нужно знать, были ли эти точки искажены глобально. Даже если часы спешат или опаздывают на 112 лет 5 часов 10 минут и 1 секунду (или другое значение), это не отражается на разности между ними. Единственное, что важно, — после того, как мы сохраняем временную точку tic, и до того, как сохраняем временную точку toc, для часов нельзя выполнить микронастройку (что случается время от времени во многих системах), поскольку это исказит измерение. Согласно данным требованиям, оптимальным выбором является steady_clock. Их реализация может быть основана на счетчике временных меток процессора, который всегда монотонно увеличивается с момента запуска системы.
О’кей, теперь, когда мы выбрали правильный объект time, можем сохранить временные точки с помощью функции chrono::steady_clock::now(). Функция now возвращает значение типа chrono::time_point<chrono::steady_clock>. Разность между двумя такими значениями (toc–tic) является временным промежутком, или продолжительностью, имеющей тип chrono::duration.
Поскольку данный тип является основным для текущего раздела, все немного усложняется. Рассмотрим интерфейс шаблонного типа duration более пристально:
template<
class Rep,
class Period = std::ratio<1>
> class duration;
Можно изменить значения параметров Rep и Period. Значение параметра Rep объяснить легко: это всего лишь численный тип переменной, который используется для сохранения значения времени. Для существующих в STL единиц измерения времени таковым обычно выступает тип long long int. В данном примере мы выбрали тип double и благодаря этому можем сохранять по умолчанию значения в секундах, а затем преобразовывать их в милли- или микросекунды. Если у нас есть промежуток времени, равный 1.2345 секунды и имеющий тип chrono::seconds, то значение будет округлено до одной целой секунды. Таким образом, нужно сохранить разность между переменными tic и toc в переменной типа chrono::microseconds, а затем преобразовать его в менее точные единицы. Из-за выбора типа double для Rep можно выполнять преобразование к более и менее точным единицам и терять минимальный объем точности, что не влияет на наш пример.
Мы использовали Rep = double для всех единиц измерения времени, поэтому они отличаются значением параметра Period:
using seconds = chrono::duration<double>;
using milliseconds = chrono::duration<double,
ratio_multiply<seconds::period, milli>>;
using microseconds = chrono::duration<double,
ratio_multiply<seconds::period, micro>>;
Секунды — самая простая в описании единица времени, поскольку можно воспользоваться