Я разработчик библиотеки с открытым исходным кодом. Один из наших классов оформлен шаблонами для множества разных типов. В настоящее время определение находится в файле заголовка, что отрицательно влияет на время компиляции, а также заставляет пользователей включать больше заголовков, чем необходимо. Моя цель такова:
-
Чтобы сократить время компиляции, я хочу использовать явное выражение о создании, введенное с С++ 11.
-
Определение методов класса и членов, все из которых являются статическими, должно быть отделено от объявления в файле реализации. Они должны быть доступны для использования снаружи и внутри библиотеки, если пользователи не должны выполнять явное определение экземпляра или что-то в этом роде.
-
Это должно выполняться кросс-платформой для всех распространенных компиляторов, которые поддерживают С++ 11 (Visual Studio 2013+, GCC и т.д.)
С++ 11 предоставляет новые возможности для шаблонов классов, в частности " явная декларация о создании. Насколько я понимаю, это можно использовать в этом контексте. Предыдущие вопросы касались этого в аналогичных контекстах, например. Как использовать шаблон extern и Разделение определения/создания классов шаблонов без "extern" , но это не касается с экспортом библиотек и их решением вызывают ошибки компоновщика, если клиент пытается использовать общую библиотеку.
В настоящее время мне удалось реализовать это способом, который он компилирует, связывает и запускает на Visual Studio 2015, но я не уверен, правильно ли я использую ключевые слова, особенно __declspec в этом случае. Это то, что я получил (упрощен):
// class.h
template<typename T>
class PropertyHelper;
template<typename T>
class PropertyHelper<const T>
{
public:
typedef typename PropertyHelper<T>::return_type return_type;
static inline return_type fromString(const String& str)
{
return PropertyHelper<T>::fromString(str);
}
static const int SomeValue;
};
template<>
class EXPORTDEF PropertyHelper<float>
{
public:
typedef float return_type;
static return_type fromString(const String& str);
static const int SomeValue;
};
extern template EXPORTDEF class PropertyHelper<float>;
Последняя строка - это явная декларация о создании. Насколько я понимаю, это означает, что клиентам не нужно декларировать это каждый раз. EXPORTDEF
- это определение, которое является либо __declspec (dllexport), либо __declspec (dllimport) в Windows. Я не уверен, что мне нужно поместить это в строку выше, потому что следующее также компилирует, связывает и запускает:
extern template class PropertyHelper<float>;
Файл cpp выглядит следующим образом:
const int PropertyHelper<float>::SomeValue(12);
PropertyHelper<float>::return_type
PropertyHelper<float>::fromString(const String& str)
{
float val = 0.0f;
if (str.empty())
return val;
//Some code here...
return val;
}
template class PropertyHelper<float>;
Последняя строка - это явное определение экземпляра.
Итак, мой вопрос больше всего, если я сделал все правильно здесь в соответствии со стандартом С++ 11, а во-вторых (если это правда), если ключевое слово __declspec является избыточным в контексте явной декларации о создании, или что я должен сделать это, так как я не нашел надлежащей информации в документах MSDN.