Так что я попал в затруднительное положение с шаблонами C++. Предполагая, что у меня есть иерархия контейнерных классов вида:
template <class T>
class AContainer{
// ...
};
И через наследование делаются разные контейнеры с разными внутренними представлениями:
template <class T>
class AVectorLikeContainer: public AContainer<T>{
// ...
};
И куча иерархий оператороподобных классов, которые имеют форму:
template <template <class T> class C, class T>
class AnOperator{
public:
virtual T operator() (const C<T> &c1, const C<T> &c2);
// ...
};
Используя операторы наследования и частичной специализации, такие как эти:
template <class T>
class AnOperatorForVectorLike: public AnOperator<AvectorLikeContainer, T>{
public:
virtual T operator() (const AVectorLikeContainer<T> &c1, const AVectorLikeContainer<T> &c2);
// ...
};
Теперь чуть позже в проекте контейнеры вида:
template <class T, std::size_t N>
class AStaticSizeContainer: public AContainer<T>{
// ...
};
были введены. Очевидно, что это нарушает дизайн, поскольку AStaticSizeContainer
не соответствует части template <class T> class C
сигнатуры шаблона AnOperator
. Чтобы обойти это, нужно ввести метафункцию, например:
template <class T, std::size_t N>
class StaticSizer{
public:
template <class T1>
class SizedStaticContainer: public AStaticSizeContainer<N, T1>{
// ...
};
};
Таким образом, StaticSizer<25>::SizedStaticContainer
— это класс, соответствующий сигнатуре шаблона template <class T> class C
. Однако у этого есть несколько недостатков. Первый и очевидный — это необходимость всегда использовать StaticSize<N>::SizedStaticContainer<T>
вместо AStaticSizeContainer<T, N>
, даже если T
и N
«известны». Это вызвано тем, что они не взаимозаменяемы (один наследуется от другого). Второй недостаток заключается в том, что все конструкторы AStaticSizeContainer
должны быть буквально скопированы для StaticSizer::SizedStaticContainer
. Я уверен, что есть и другие, на которые я еще не наткнулся.
Итак, мои вопросы следующие:
Есть ли более элегантный способ исправить это в соответствии с уже выложенным интерфейсом? В более широком смысле, можем ли мы указать частичную специализацию класса более элегантным способом? В более узком смысле, есть ли у нас синтаксис, чтобы сказать что-то вроде:
template <class T, std::size_t N>
class AnOperatorForStaticSize: public AnOperator<AStaticSizeContainer<with N = N>, T>{
// ...
};
где под AStaticSizeContainer<with N = N>
я подразумеваю частичную специализацию AStaticSizeContainer
с N
из приведенного выше шаблона.
ИЗМЕНИТЬ C++11 шаблоны псевдонимов, по-видимому будет работать, но мне нужна альтернатива С++ 03.