Я хочу написать библиотеку, которую нужно использовать, вам нужно включить только один заголовочный файл. Однако, если у вас есть несколько исходных файлов и они включают заголовок в обоих, вы получите несколько ошибок определения, потому что библиотека объявлена и определена в заголовке. Я видел библиотеки только для заголовков, в Boost, я думаю. Как они это сделали?
Библиотеки только для заголовков и многочисленные ошибки определения
Ответ 1
Объявите свои функции inline
и поместите их в пространство имен, чтобы вы не сталкивались:
namespace fancy_schmancy
{
inline void my_fn()
{
// magic happens
}
};
Ответ 2
Основная причина, по которой Boost в основном относится только к заголовку, заключается в том, что он сильно ориентирован на шаблоны. Шаблоны обычно получают пропуск от одного правила определения. Фактически для эффективного использования шаблонов вы должны иметь определение, видимое в любой единицы перевода, которая использует шаблон.
Другим способом, связанным с одним правилом определения (ODR), является использование функций inline
. Фактически, получение свободного прохода от ODR - это то, что действительно делает inline
- тот факт, что он может встроить функцию, действительно является скорее дополнительным побочным эффектом.
Окончательный вариант (но, вероятно, не такой хороший) заключается в том, чтобы сделать ваши функции статичными. Это может привести к раздуванию кода, если компоновщик не может понять, что все эти экземпляры функций действительно одинаковы. Но я упомянул об этом для полноты. Обратите внимание, что компиляторы часто выполняют функции static
, даже если они не помечены как inline
.
Ответ 3
Boost использует библиотеки только для заголовков, потому что, подобно STL, он в основном построен с использованием шаблонов классов и функций, которые почти всегда имеют только заголовок.
Если вы не пишете шаблоны, я бы избегал включать код в ваши файлы заголовков - это больше проблем, чем того стоит. Сделайте это простой старой статической библиотекой.
Ответ 4
Есть много действительно богатых только Boost библиотек, но они, как правило, очень простые (и/или только шаблоны). Большие библиотеки выполняют один и тот же эффект с помощью некоторого обмана: у них есть "автоматическая привязка" (вы увидите, что этот термин используется здесь). У них по существу есть куча препроцессорных директив в заголовках, которые определяют соответствующий файл lib для вашей платформы и используют #pragma
, чтобы дать ссылку компоновщику связать его. Таким образом, вам не нужно явно связывать его, но это все еще связаны.