Когда мне следует подумать о создании библиотеки только для заголовков?
Очевидно, что библиотеки шаблонов должны быть только заголовками, но для не-шаблонов, когда вы должны делать вещи только для заголовков?
4 ответа
Если вы думаете, что ваша не шаблонная библиотека может быть только для заголовка, попробуйте в любом случае разделить ее на два файла, а затем предоставить третий файл, который включает оба .h
и .cpp
(с включенным охранником).
Тогда любой, кто использует вашу библиотеку во многих различных TU и подозревает, что это может потребовать много времени на компиляцию, может легко внести изменения, чтобы протестировать ее.
Как только вы узнаете, что у пользователей есть возможность использовать библиотеку, ответом, вероятно, станет "предложите эту опцию, когда это возможно". Настолько, что включение его из нескольких TU не нарушало бы ODR. Например, если вашstatic
бесплатные функции относятся к static
глобальные, тогда вам не повезло, так как разные определения этой функции в разных TU будут ссылаться на разные объекты с одинаковыми именами, что является ODR-нарушением.
Вы можете последовать примеру Boost.Asio.
Они просто предоставляют две версии библиотек: только заголовок и заголовок + библиотека.
Они делают это с помощью одного макроса, который должен быть определен (или нет) перед включением их заголовков. Я думаю, что по умолчанию (если не определено) является использование версии только для заголовка.
См. Необязательный отдельный сборник.
Обратите внимание, как они аккуратно предоставляют один исходный файл для компиляции, который определяет все или возможность связываться с динамически загружаемой библиотекой.
Библиотеки шаблонов не обязательно должны быть только заголовками: реализации могут вполне содержать некоторые части, не зависящие от параметров шаблона, и по некоторым причинам (например, меньший размер кода) разделяться на специальный двоичный файл.
Я не могу представить себе случай, когда не шаблонная библиотека действительно должна быть только заголовочной. Однако иногда может быть разумно с точки зрения производительности разрешить встраивание всего кода. Примером может служить библиотека оберток вокруг специфичных для платформы интерфейсов, например, для таких вещей, как примитивы синхронизации, локальное хранилище потоков, специфичная для платформы и компилятора реализация атомарных операций и т. Д.
Без шаблонов у вас были бы реальные определения в заголовках. Это означает, что если два файла содержат ваш заголовок, вы получите несколько определений, и код не будет компилироваться.
Другими словами, помещать определения в заголовки - очень плохая идея. Вы должны придерживаться только объявлений и шаблонов.
Что касается шаблонов, компиляторы знают, что вы можете включать один и тот же заголовок более одного раза, они не будут генерировать один и тот же код снова и снова.
РЕДАКТИРОВАТЬ: Если вы имеете в виду "держать все в курсе", я думаю, что это очень плохой подход. Заголовочные файлы становятся полностью нечитаемыми, и любое изменение в реализации заставляет любого пользователя вашей библиотеки все перекомпилировать.