У меня есть такой класс:
struct Base
{
void aa(int n) const {
std::cout << "aa() " << field*n << std::endl;
}
void bb(int n) const {
std::cout << "bb() " << field*n*2 << std::endl;
}
int field = 2;
};
Я хочу иметь возможность выбирать, во время компиляции , одну из двух реализаций, aa()
или bb()
, через вызов метода оператора. Что-то вроде:
Base data;
Magic obj(data);
obj.as_AA() * 33; // should call data.aa(33)
obj.as_BB() * 44; // should call data.bb(44)
data
не должно дублироваться. И выбор aa()
против bb()
должен быть решен во время компиляции.
У меня есть решение, которое использует понижающее преобразование, поведение которого теоретически не определено (я думаю). Он строится (с g ++ и clang ++) и работает отлично, но все же ...
struct AA : public Base
{
void operator*(int n) const {
return Base::aa(n);
}
};
struct BB : public Base
{
void operator*(int n) const {
return Base::bb(n);
}
};
struct Chooser
{
Base obj;
template<typename WHICH> // will be either AA or BB
const WHICH& as() const {
return static_cast<const WHICH&>( obj ); // downcasting
}
};
В main.cpp
:
Chooser ch;
ch.as<AA>() * 5; // prints "aa() 10"
ch.as<BB>() * 7; // prints "bb() 28"
Насколько ненадежно мое решение? (из-за понижения, которое технически не определено)
Видите ли вы альтернативы?
Спасибо
ps: конечно, я мог бы тривиально использовать
Base data;
data.aa(33);
data.bb(44);
, но я действительно хочу получить доступ к различным реализациям через одно и то же имя ie., Оператор *
Я также мог бы использовать шаблонный оператор * в Base
и иметь явную специализацию шаблона, однако это вынудило бы меня использовать уродливый синтаксис, который аннулирует назначение оператора:
struct Base {
\\...
template<int N> void operator*(int n) const;
};
template<> void Base::operator*<1>(int n) const {
aa(n);
}
Для чего требуется:
Base data;
data.operator*<1>(44); // ugly