2016-12-02 102 views
1

由於返回類型問題,我們不能直接製作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*>SU沒有共同的祖先。如果我從另一個基類派生A,我還必須將模板部分移到那裏,問題 - 哈! - 遞歸。

那麼,有什麼建議嗎?

編者注:已經吸取了教訓,我保存了原來的這個時候。 :)

+2

我不知道我完全理解你的問題。你需要一個基類'A',它將有'++'運算符,但是它們的實現可以在派生類中被覆蓋。是這樣嗎? – Angew

+0

@Angew我想要一種解決虛擬函數返回類型(表面上是人爲的)限制的方法。最初,虛擬函數根本不能返回不同的類型;然後放寬到協變類型。總比沒有好,但仍然不夠。後綴增量僅僅是這個特性變得特別不合邏輯的例子。 – sigil

回答

0

我不認爲這是可能的C++類型系統中,這是爲什麼:

請看下面的例子:假設我們以某種方式實現這一點,必須A* a指針基類,US被派生出來。那麼var = (*a)++;的類型是什麼?它可以是US,具體取決於a指向的內容。但是編譯器需要知道編譯期間返回類型因爲操作++(int)的返回SU的價值。

我看到下面的方法來解決這個問題,但它們都需要改變返回類型的層次operator++(int),使它們協(見C++ virtual function return type):

  1. 返回指針(基地)您的層次結構

  2. 類內如果你的類型是整數類型(如運營商++返回charintlong不同類別),那麼你可以讓他們都返回封閉類型:long int

  3. ,而不是返回的對象(US)的直接值返回某種結構是能夠保持這些類型的任何的。 (請參閱http://www.boost.org/doc/libs/1_61_0/doc/html/any.html可能的通用方法來做到這一點)

+0

'boost :: any'也是我最初的賭注。但是,它不會允許我對存儲值進行任何有用的操作,只會將它們恢復爲**靜態**已知類型。(或者通過一系列比較字符串的'if-else'語句來運行它們,這種方式會破壞整個想法。)如果您有一個使用boost :: any的例子,請分享。 – sigil

+0

那麼,看看高層次的圖片:如果代碼不知道_anything_關於存儲​​值 - 它將無法使用它。所以代碼需要知道_something_關於存儲​​在'any'中的類型。例如,它可能會嘗試檢查結果是否屬於一個或另一個繼承層次結構,並調用適合它的虛函數,而「any」類允許您實現這一點。 – Yatima

相關問題