Похоже, что вы используете enum для передачи информации о типе от пользователя.Я хотел бы предложить, чтобы вы этого не сделали.
В простейшем случае, если f1
и f2
переименованы в f
, вы можете удалить if
и просто вызвать его.Компилятор вызовет соответствующую перегрузку для вас.
Если вы не можете или не хотите переименовывать шаблоны функций, вы можете написать вспомогательный шаблон, который будет отправлять вам (базовый шаблон класса не определен, специализации дляA
и B
, которые отправляют соответствующую статическую функцию)
Если перечисление используется для чего-то другого (что компилятор не может разрешить для вас), вы все равно можете передать его и переписать помощник длядиспетчеризируйте перечисление, а не тип аргумента, и вам придется переписать код, чтобы значение перечисления было константой времени компиляции (самое простое: передать его как аргумент шаблона в algo
).В этом случае вы можете написать специализацию функции вместо классов, если хотите, поскольку они будут полными специализациями.Но учтите, что если вам удастся избежать его передачи, вы удалите целое семейство ошибок: передав неправильное значение перечисления.
// Remove the enum and rename the functions to be overloads:
//
struct C { // If everything is static, you might want to consider using a
// namespace rather than a class to bind the functions together...
// it will make life easier
template <typename T>
static void f( A<T> & ) { /* implement A version */ }
template <typename T>
static void f( B<T> & ) { /* implement B version */ }
template <typename T> // This T is either A<U> or B<U> for a given type U
static void algo( T & arg ) {
// common code
f( arg ); // compiler will pick up the appropriate template from above
}
};
Для других альтернатив проще, если охватывающая область является пространством имен, но идея была бы такой же (может потребоваться немного сложнее бороться с синтаксисом:
template <typename T>
struct dispatcher;
template <typename T>
struct dispatcher< A<T> > {
static void f( A<T>& arg ) {
C::f1( arg );
}
};
template <typename T>
struct dispatcher< B<T> > {
static void f( B<T>& arg ) {
C::f2( arg );
}
};
template <typename T>
void C::algo( T & arg ) {
// common code
dispatcher<T>::f( arg );
}
Опять же, заставить работать с классом немного сложнее, так как, вероятно, потребуется парапредварительных деклараций, и у меня нет компилятора под рукой, но эскиз должен привести вас в правильном направлении.