- Фантастика и фэнтези
- Ироническое фэнтези
- Стимпанк
- Детективная фантастика
- Киберпанк
- Попаданцы
- LitRPG
- Космоопера
- Технофэнтези
- Городская фантастика
- Русское фэнтези
- Юмористическая фантастика
- Космическая фантастика
- Боевое фэнтези
- Эпическая фантастика
- Зарубежная фантастика
- Книги магов
- Мистика
- Разная фантастика
- Разное фэнтези
- Любовное фэнтези
- Романтическая фантастика
- Городское фентези
- Историческая фантастика
- Историческое фэнтези
- Социально-философская фантастика
- Сказочная фантастика
- Иностранное фэнтези
- Романтическое фэнтези
- Ироническая фантастика
- Ужасы и Мистика
- Постапокалипсис
- Героическая фантастика
- Фэнтези
- Научная Фантастика
- Социально-психологическая
- Альтернативная история
- Боевая фантастика
- Разная литература
- Пословицы, поговорки
- Шахматы
- Визуальные искусства
- Фанфик
- Авто и ПДД
- Военное
- Отраслевые издания
- Гиды, путеводители
- Зарубежная образовательная литература
- Военная история
- Цитаты из афоризмов
- Современная литература
- Великолепные истории
- Начинающие авторы
- Современная зарубежная литература
- Боевые искусства
- Изобразительное искусство, фотография
- Кино
- Литература 19 века
- Недвижимость
- Музыка, музыканты
- Готические новеллы
- Истории из жизни
- Культура и искусство
- Спецслужбы
- Зарубежная прикладная литература
- Музыка, танцы
- Подростковая литература
- Прочее
- Военная техника, оружие
- Газеты и журналы
- Периодические издания
- Домоводство, Дом и семья
- Любовные романы
- Экономическая литература
- Научные и научно-популярные книги
- О животных
- Биохимия
- Культурология
- Юриспруденция
- Политика
- Психотерапия
- Языкознание
- Научпоп
- Медицина
- Психология, личное
- Радиотехника
- Филология
- Педагогика
- Образовательная литература
- Деловая литература
- Физика
- Науки: разное
- Химия
- Воспитание детей, педагогика
- Детская психология
- Зарубежная публицистика
- Биология
- Архитектура
- Зарубежная психология
- Науки о космосе
- Социология
- Математика
- География
- Беременность, ожидание детей
- Литературоведение
- Транспорт, военная техника
- Обществознание
- Зоология
- География
- Альтернативная медицина
- Иностранные языки
- Ветеринария
- Рефераты
- Астрология
- Биофизика
- Экология
- История Европы
- Учебники
- Шпаргалки
- Государство и право
- Ботаника
- Религиоведение
- История
- Техническая литература
- Прочая научная литература
- Психология
- Детективы и Триллеры
- Справочная литература
- Проза
- Новелла
- Юмор
- Проза
- Историческая проза
- Русская современная проза
- Советская классическая проза
- Повести
- Очерки
- Эссе
- Рассказы
- Зарубежная современная проза
- Сентиментальная проза
- Зарубежная классика
- Афоризмы
- Эпистолярная проза
- Феерия
- Семейный роман/Семейная сага
- Разное
- Антисоветская литература
- Магический реализм
- Русская классическая проза
- Современная проза
- О войне
- Контркультура
- Классическая проза
- Поэзия, Драматургия
- Детская литература
- Детская фантастика
- Детские остросюжетные
- Детские стихи
- Детские приключения
- Внеклассное чтение
- Учебная литература
- Зарубежные детские книги
- Бизнес
- Загадки
- Книги для подростков
- Школьные учебники
- Детский фольклор
- Книги для дошкольников
- Детские детективы
- Детская познавательная и развивающая литература
- Буквари
- Прочая детская литература
- Сказка
- Детская проза
- Детская образовательная литература
- Юмор
- Документальные книги
- Бизнес
- Внешнеэкономическая деятельность
- Тайм-менеджмент
- Кадровый менеджмент
- О бизнесе популярно
- Управление, подбор персонала
- Бизнес
- Менеджмент и кадры
- Продажи
- Экономика
- Ценные бумаги и инвестиции
- Малый бизнес
- Делопроизводство, офис
- Корпоративная культура, бизнес
- Банковское дело
- Финансы
- Зарубежная деловая литература
- Ораторское искусство / риторика
- Личные финансы
- Интернет-бизнес
- Поиск работы
- Государственное и муниципальное управление
- Бухучет и аудит
- Работа с клиентами
- Менеджмент
- Краткое содержание
- Личная эффективность
- Переговоры
- Приключения
- Старинная литература
- Религия и духовность
- Компьютеры и Интернет
- Блог
Читаем без скачивания C++17 STL Стандартная библиотека шаблонов - Яцек Галовиц
Шрифт:
Интервал:
Закладка:
Здесь мы сначала преобразуем экземпляр типа chrono::time_point<chrono::system_clock> к типу std::time_t. Значения этого типа можно преобразовать в локальное время, что мы делаем с помощью функции std::localtime. Она возвращает указатель на преобразованное значение (не волнуйтесь об управлении памятью, лежащей за данным указателем; это статический объект, и для него память в куче не выделяется), которое мы наконец можем вывести на экран.
Функция std::put_time принимает такой объект и строку формата. Строка "%c" отображает стандартную строку даты-времени, например "Sun Mar 12 11:33:40 2017".
Мы также могли бы указать строку "%m/%d/%y", и тогда программа вывела бы на экран дату в формате 03/12/17. Весь список существующих форматов времени слишком длинный, он хорошо задокументирован в онлайн-справочнике по С++.
Помимо вывода на экран мы добавили смещения к нашему моменту времени. Это было просто, поскольку можно выразить промежутки времени, такие как 12 часов 15 минут, в виде 12h+15min. Пространство имен chrono_literals предоставляет удобные литералы типов для часов (h), минут (min), секунд (s), миллисекунд (ms), микросекунд (us) и наносекунд (ns).
Добавление подобной продолжительности к значению момента времени создает новое значение момента времени, поскольку типы имеют соответствующие перегруженные версии операторов + и –, именно поэтому так легко добавлять и отображать смещения времени.
Безопасно извещаем о сбое с помощью std::optional
Когда программа общается с внешним миром и полагается на значения, получаемые извне, могут происходить всевозможные сбои.
Это означает вот что: когда мы пишем функцию, которая должна возвращать значение, но также может дать сбой, это нужно отразить с помощью неких изменений в интерфейсе функции. У нас есть несколько вариантов. Посмотрим, как разработать интерфейс функции, которая возвращает строку, но способна дать сбой:
□ использовать возвращаемое значение, указывающее на успех, и выходные параметры: bool get_string(string&);;
□ возвращать указатель (или умный указатель), значение которого можно установить на nullptr в случае сбоя: string* get_string();;
□ генерировать исключение в случае сбоя и оставить сигнатуру функции очень простой: string get_string();.
Все эти подходы имеют свои преимущества и недостатки. Начиная с C++17, существует новый тип, который можно применять для решения такой задачи другим способом: std::optional. Идея необязательных значений происходит из чисто функциональных языков программирования (там они иногда называются типами Maybe (может быть)) и позволяет писать очень изящный код.
Мы можем обернуть в тип optional наши собственные типы, чтобы указать на пустые или ошибочные значения. Ниже мы узнаем, как это делается.
Как это делается
В этом примере мы реализуем программу, которая считывает целые числа, поступающие от пользователя, и складывает их. Поскольку пользователь всегда может ввести случайные символы вместо чисел, мы увидим, как тип optional способен улучшить обработку ошибок.
1. Сначала включим все необходимые заголовочные файлы и объявим об использовании пространства имен std:
#include <iostream>
#include <optional>
using namespace std;
2. Определим целочисленный тип, который, может быть, содержит значение. Нам идеально подойдет тип std::optional. Обернув любой тип в тип optional, задаем ему еще одно возможное состояние, которое отражает тот факт, что тип не имеет значения:
using oint = optional<int>;
3. Определив необязательный целочисленный тип, можем выразить тот факт, что функция, которая возвращает целое число, тоже способна дать сбой. Если мы возьмем целое число из пользовательских входных данных, то существует вероятность сбоя, поскольку пользователь может ввести какой-то другой символ, несмотря на наше приглашение. Возврат целого числа, обернутого в тип optional, идеально решает эту проблему. Если нам удалось считать целое число, то передадим его конструктору типа optional<int>. В противном случае вернем экземпляр типа optional, созданный с помощью конструктора по умолчанию, что говорит о сбое или пустоте.
oint read_int()
{
int i;
if (cin >> i) { return {i}; }
return {};
}
4. Наши возможности не ограничиваются возвратом целых чисел из функций, способных дать сбой. Что если мы подсчитаем сумму двух целых чисел, которые могут не содержать значений? Мы получим реальную численную сумму только в том случае, если оба операнда содержат значения. В любом другом нужно вернуть пустую переменную типа optional. Эту функцию следует немного пояснить: неявно преобразуя переменные типа optional<int>, a и b, к булевым выражениям (с помощью конструкций !a и !b), мы узнаем, содержат ли они реальные значения. Если да, то можно получить к ним доступ как к указателям или итераторам, просто разыменовав их с использованием конструкций *a и *b:
oint operator+(oint a, oint b)
{
if (!a || !b) { return {}; }
return {*a + *b};
}
5. Сложение обычного целого числа и целого числа, которое может не содержать значений, следует той же логике:
oint operator+(oint a, int b)
{
if (!a) { return {}; }
return {*a + b};
}
6. Теперь напишем программу, совершающую некие действия с целыми числами, которые могут не содержать значений. Пригласим пользователя ввести два числа:
int main()
{
cout << "Please enter 2 integers.n> ";
auto a {read_int()};
auto b {read_int()};
7. Сложим эти числа, а затем добавим к полученной сумме значение 10. Поскольку a и b могут не иметь значений, sum также будет необязательной целочисленной переменной:
auto sum (a + b + 10);
8. Если переменные a и/или b не содержат значений, то sum не может иметь значения. Положительный момент заключается в том, что не нужно явно проверять значения переменных a и b. Сложение пустых экземпляров типа optional — полностью корректное поведение, поскольку мы определили безопасный оператор + для этих типов. Таким образом можно произвольно сложить несколько пустых необязательных экземпляров, а проверять нужно только полученный экземпляр. Если он содержит значение, то мы можем безопасно получить к нему доступ и вывести его на экран:
if (sum) {
cout << *a << " + " << *b << " + 10 = "
<< *sum << 'n';
9. Если пользователь вводит не числа, то мы сообщаем об ошибке: