由于返回类型问题,我们无法直接生成operator++(int)
virtual
。通常的建议是应用奇怪命名的Curiously Recurring Template Pattern
,我最好的谦虚理解实施如下:
// 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
,我还必须将模板化部分移到那里并解决问题 - 哈! - 递归。
那么,有什么建议吗?
编者注:在吸取了教训后,我这次保存了原文。 :)
答案 0 :(得分:0)
我不认为在C ++类型系统中这是可能的,这就是为什么:
请考虑以下示例:假设我们以某种方式实现此目标并且具有指向A* a
和U
的基类的S
指针。那么var = (*a)++;
的类型是什么?它可以是U
或S
,具体取决于a
指向的内容。但编译器需要在编译期间知道返回类型 ,因为operator ++(int)返回S
和U
by-value。
我看到以下解决此问题的方法,但他们都需要更改层次结构中operator++(int)
的返回类型以使其协变(请参阅C++ virtual function return type):
返回指向层次结构中(基类)的指针
如果你的类型是整数类型(比如operator ++返回char
,int
,long
用于不同的类)那么你可以让它们全部返回封闭类型:{{1 }}
不是返回对象的直接值(long int
或U
),而是返回某种能够保存这些类型的结构。 (有关可能的通用方法,请参阅http://www.boost.org/doc/libs/1_61_0/doc/html/any.html)