Ответ 1
Если шаблон templated, ваши пользователи по существу должны скомпилировать его (и это буквально верно в наиболее широко используемых реализациях С++), и поэтому им нужны ваши внешние зависимости.
Самое простое решение - поместить основную часть вашей реализации класса в базовый класс без шаблона (или инкапсулированный объект-член какого-либо класса). Решите проблему сокрытия модуля.
И затем напишите полученный шаблон (или окружение), чтобы добавить к нему безопасность типа.
Например, предположим, что у вас есть шаблон, который обеспечивает удивительную способность выделять при первом доступе (опускает необходимый конструктор, назначение, деструктор):
template <class T>
class MyContainer
{
T *instance_;
public:
MyContainer() : instance_(0) {}
T &access()
{
if (instance_ == 0)
instance_ = new T();
return *instance_;
}
};
Если вы хотите, чтобы "логика" была разделена на базовый класс без шаблона, вам нужно было бы параметризовать поведение в режиме без шаблонов, то есть использовать виртуальные функции:
class MyBase
{
void *instance_;
virtual void *allocate() = 0;
public:
MyBase() : instance_(0) {}
void *access()
{
if (instance_ == 0)
instance_ = allocate();
return instance_;
}
};
Затем вы можете добавить понимание типа во внешнем слое:
template <class T>
class MyContainer : MyBase
{
virtual void *allocate()
{ return new T(); }
public:
T &access()
{ return *(reinterpret_cast<T *>(MyBase::access())); }
};
то есть. Вы используете виртуальные функции, чтобы позволить шаблону "заполнить" операции, зависящие от типа. Очевидно, что эта схема будет иметь смысл только в том случае, если у вас есть бизнес-логика, которая стоит усилий для скрытия.