简体   繁体   English

是否可以完全模拟虚拟运算符++(int)?

[英]Is it possible to fully emulate a virtual operator++(int)?

We cannot make operator++(int) virtual directly because of the return type problem. 由于返回类型问题,我们无法直接使operator++(int) virtual The usual advice is to apply the curiously named Curiously Recurring Template Pattern , which I implemented to the best of my modest understanding as follows: 通常的建议是应用奇怪的名为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;
};

Lots of code duplication, but at least it allows for constructs like the following to run, which is definitely a start: 很多代码重复,但至少它允许运行以下结构,这绝对是一个开始:

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;
}

Sadly, it does not help with things like vector<A*> : S and U have no common ancestor. 可悲的是,它对vector<A*> <A *>之类的东西没有帮助: SU没有共同的祖先。 If I derive A from another base class, I also have to move the templated part there and the problem - ha! 如果我从另一个基类派生A ,我还必须将模板化部分移动到那里并且问题 - 哈! - goes recursive. - 递归。

So, any suggestions? 那么,有什么建议吗?

Note to editors: Having learned my lesson, I saved the original this time. 编者注:在吸取教训后,我这次保存了原文。 :) :)

I do not think this is possible within C++ type system, here is why: 我不认为这在C ++类型系统中是可能的,这就是为什么:

Consider the following example: Let say we somehow achieve this and have A* a pointer to the base class from which U and S was derived. 考虑下面的例子:假设我们以某种方式实现了这个并且让A* a指向从中派生US的基类A* a指针。 Then what will be the type of the var = (*a)++; 然后var = (*a)++;的类型是什么var = (*a)++; ? It could be either U or S depending on what a is pointing to. 它可以是US这取决于a指向。 But compiler need to know return type during compilation because operator++(int) return S and U by-value. 但编译器需要在编译期间知道返回类型因为operator ++(int)返回SU by-value。

I see the following ways to work around this problem but they all need to change the return types of operator++(int) in hierarchy to make them covariant (see C++ virtual function return type ): 我看到以下解决此问题的方法,但是他们都需要更改层次结构中的operator++(int)的返回类型以使它们协变(请参阅C ++虚函数返回类型 ):

  1. Return pointer to a (base) class within your hierarchy 返回指向层次结构中(基类)的指针

  2. If your types is integer types (like operator++ return char , int , long for different classes) then you can make them all return enclosing type: long int 如果你的类型是整数类型(比如operator ++ return charintlong for different classes)那么你可以让它们全部返回封闭类型: long int

  3. Instead of returning direct values of your objects ( U or S ) return some kind of struct that is capable of holding any of these types. 而不是返回你的对象(直接值的US )返回某种结构,它能够持有任何这些类型的。 (see http://www.boost.org/doc/libs/1_61_0/doc/html/any.html for possible generic way to do this) (有关可能的通用方法,请参阅http://www.boost.org/doc/libs/1_61_0/doc/html/any.html

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM