Как создать базовые шаблоны классов явно?

Этот вопрос рассматривает явное воплощение шаблонных классов.

Рассмотрим шаблонный класс B<T> производный от другого шаблона класса A<T>, Я хочу явно создать экземпляр B<T> потому что его методы должны вызываться из динамического связывания, поэтому методы должны быть созданы, хотя они не вызываются в самом коде. Конечно, также методы, унаследованные от A<T> будет называться, поэтому они должны быть также созданы.

Кажется, что C ++ НЕ создает экземпляры базовых классов при явном создании экземпляра шаблонного класса, как задано в этом вопросе:
Инстанцируют ли явные экземпляры шаблонов классов C ++ зависимые базовые классы?
Пример:

template<typename T>
class A{ void foo(){...} };

template<typename T>
class B : public A<T> {}

template class B<int>; // This will NOT instanciate A<int>::foo()!!!

Конечно, мне также нужно создать все базовые классы. Однако я не хочу обременять код клиента этим, потому что иерархия классов может быть очень глубокой. Рассмотрим иерархию классов, включающую 10 или более шаблонных классов. Не следует призывать клиента написать 10 явных шаблонных экземпляров. Это не только много написания; это также сломается, когда я внесу изменения в иерархию классов.

Вместо этого я хочу достичь B<T> инстанцируется, как и все его базовые классы. Я попытался просто создать экземпляр базового класса в самом B:

template<typename T>
class B : public A<T> {
template class A<T>; // Does not compile!
}

Но это не компилируется. Есть ли другие способы, которые могли бы достичь этого?

9

Решение

Может быть, не элегантно, но по крайней мере выполнимо: предоставьте макрос для создания экземпляра шаблона и потребуйте от пользователя использовать макрос вместо ручного создания экземпляра:

// in A.hpp
#define INSTANTIATE_A(T) template class A<T>;

// in B.hpp
#define INSTANTIATE_B(T) \
INSTANTIATE_A(T)     \
template class B<T>;

И если вы предпочитаете «загрязнять» интерфейс класса принудительному использованию макроса экземпляра: добавьте protected член, который вызывает все другие функции-члены шаблона и версии в базовом классе. Пример:

template<typename T>
class A
{
void foo() {...}
protected:
void instantiate() { foo(); }
};

template<typename T>
class B : public A<T>
{
void bar() {...}
protected:
void instantiate() { A<T>::instantiate(); bar(); }
};

template class B<int>; // Now works as expected

Обновить:

Альтернатива второму решению: взять указатель на функцию всех членов и сохранить их во временную переменную:

template<typename T>
class A
{
void foo() {...}
protected:
void instantiate() { void (A::*p)() = &A::foo; }
};

template<typename T>
class B : public A<T>
{
void bar() {...}
protected:
void instantiate() { A<T>::instantiate(); void (B::*p)() = &B::foo; }
};
2

Другие решения


По вопросам рекламы [email protected]