Мы не можем сделать operator++(int)
virtual
непосредственно из-за проблемы с возвратом. Обычный совет применить любопытное название Curiously Recurring Template Pattern
, который я реализовал в меру моих скромных пониманий следующим образом:Можно ли полностью эмулировать виртуальный оператор ++ (int)?
// abstract numeric type
template <typename T>
class A {
public:
virtual T& operator++() = 0;
virtual T get() const = 0;
virtual string toString() const = 0;
virtual T operator++(int) {
T old(this->get());
++*this; // calls operator++() from derived class
return old;
}
friend ostream& operator<<(ostream& os, const A& a) {
return os << a.toString();
}
virtual ~A() = 0;
};
// signed numeric type
class S : public A<S> {
public:
S(long l) : m_l(l) {}
virtual S get() const { return m_l; }
virtual string toString() const { return to_string(m_l); }
virtual S& operator++() { // no wrapping, caps at LONG_MAX
if (m_l < LONG_MAX)
++m_l;
return *this;
}
private:
long m_l;
};
// unsigned numeric type
class U : public A<U> {
public:
U(unsigned long ul) : m_ul(ul) {}
virtual U get() const { return m_ul; }
virtual string toString() const { return to_string(m_ul); }
virtual U& operator++() { // no wrapping, caps at ULONG_MAX
if (m_ul < ULONG_MAX)
++m_ul;
return *this;
}
private:
unsigned long m_ul;
};
Много дублирования кода, но, по крайней мере, это позволяет конструкты, как следующее для запуска, который это, безусловно, начало:
template <typename T>
void pinc(A<T>& a) {
cout << a++ << ' ' << a << endl;
}
int main() {
S s(LONG_MAX);
pinc(s);
U u(LONG_MAX);
pinc(u);
return 0;
}
К сожалению, это не помогает с вещами, как vector<A*>
: S
и U
не имеют общего предка. Если я получаю A
из другого базового класса, мне также нужно переместить там шаблонную часть и проблему - ха! - идет рекурсивным.
Итак, любые предложения?
Примечание для редакторов: выучив мой урок, я сохранил оригинал на этот раз. :)
Я не уверен, что полностью понимаю ваш вопрос. Вам нужен базовый класс 'A', который будет иметь операторы' ++ ', но их реализация может быть переопределена в производных классах. Это так? – Angew
@Angew Мне нужен способ (якобы искусственное) ограничение на тип возвращаемой виртуальной функции. Первоначально виртуальные функции не могли возвращать разные типы; затем он был ослаблен ковариантными типами. Лучше, чем ничего, но все еще недостаточно. Приостановление приращения является лишь примером того, когда эта функция становится особенно нелогичной. – sigil