§ 8. Шаблоны и создание библиотек
01До этого в заданиях мы с вами писали программы, с которыми предполагается работать из командной строки путем запуска исполняемого файла через интерфейс операционной системы. Однако, с многими программами предполагается взаимодействовать путем динамического (реже статического) соединения их исполняемых файлов с исполняемыми файлами других программ. В таком случае программы называют библиотеками, поскольку в них отсутствует единая точка входа (функции main), а взамодействие с их кодом происходит посредством вызова функций по имени. 
Схема функционирования библиотек зависит от операционной системы. В Линуксе существует два типа библиотек:
- динамеческие — файлы с расширением so(англ. shared object) илиso.V.V.V, гдеVкодирует версию библиотеки, и
- статические — файлы с расширением a(англ. archive).
Статические библиотеки представляют собой архив из объектных файлов, созданных компилятором для каждого файла с исходным кодом C++ (файлы с расширением cc, C, cpp, cxx и другие). Динамические библиотеки представляют собой исполняемый файл без функции main и с некоторыми дополнительными полями, таких как версия библиотеки. Расширения файлов являются подсказкой для человека и компилятора, в общем случае можно использовать любые расширения, но тогда о типе файла придется сообщить компилятору посредством отдельного флага. 
02Для линковки статической библиотеки достаточно указать полный путь к ней в командной строке линковщика: g++ file1.o file2.o other-files.a. После этого линковщик будет использовать все объектные файлы из архива other-files.a. Для создания самой статической библиотеки из предварительно скомпилированных файлов нужна команда ar: ar -csr other-files.a file3.o file4.o. 
03Для линковки динамической библиотеки нужно указать ее имя с помощью флага -l. 
g++ file1.o file2.o -lother-files
Тогда линковщик будет искать в системных директориях файлы с названием libother-files.so (файлы с версиями после расширения используются только после установки вашей программы в систему). Если файл найдет, то его содержимое будет использоваться для определения адресов функций, вызываемых по имени в объектных файлах file1.o и file2.o. Для того чтобы добавить директории в список для поиска библиотек, испольуется флаг -L и переменная среды LD_LIBRARY_PATH, которая должна содержать список директорий, разделенных двоеточием. После флагов -l и -L не рекомендуется использовать пробел для совместимости со старыми версиями компиляторов. 
В Meson для создания статической или динамической библиотеки достаточно заменить executable на static_library или shared_library соответственно и добавить необязательный параметр version, остальные параметры этих функций такие же, как у executable: 
shared_library( 'other-files', sources: ['file3.cc', 'file4.cc'], version: meson.project_version() )
По соглашению имена файлов библиотек всегда начинаются с приставки lib, поэтому в данном примере будет создана библиотека libother-files.so, а также символьные ссылки на нее с указанием версии проекта. 
Динамические библиотеки, от которых зависит программа, загружаются в память автоматически при запуске этой программы. Загрузка рекурсивна, так что, если библиотека зависит от других библиотек, то они тоже будут загружены автоматически. Загрузить различные версии одних и тех же библиотек одновременно в рамках одной программы невозможно, поскольку это бы привело к конфликту имен. Для обхода этого ограничения некоторые библиотеки добавляют к именам своих символов (функций и глобальных переменных) версию библиотеки. Так делает, например, библиотека libc, которая является оберткой для системных вызовов Линукса. Версионирование символов библиотеки — довольно сложная операция, которой автору не приходилось заниматься, и она здесь не рассматривается. 
Задания
- Напишите классы для геометрических фигур: окружность, прямоугольник. В каждом классе должны быть поля и методы для доступа к этим полям, которых достаточно для вычисления площади. Классы являются шаблонами с одним параметром — типом числа с плавающей точкой. template <class T> class Circle; template <class T> class Rectangle; В заголовочном файле должны быть объявлены только прототипы методов, реализации методов должны находиться вcc-файле. Соберите из этих файлов динамическую библиотеку, в которой должны быть конкретизации шаблонов для чисел с плавающей точкой одинарной и двойной точности (floatиdouble).
- Подключите собранную библиотеку к программе и используйте классы для вывода площади произвольных фигур на консоль с одинарной и двойной точностью. Для подключения библиотеки к программе используйте параметр link_with:mylib = shared_library(...) executable('myapp', link_with: mylib, ...) 
- Напишите функцию my_count, которая вычисляет количество элементов в контейнере, используя итераторы начала и конца (аналогstd::distance). Эта функция должна работать с любым типом итераторов, даже если для них не определен оператор вычитания. Для итераторов с произвольным доступом должно использоваться простое вычитание, для остальных итераторов — перебор элементов. Для реализации используйтеstd::iterator_traitsиconstexpr if(см. предыдущие слайды).
- Напишите тест, которые проверит работу my_countдля вектора и списка.