2017-02-24 155 views
0

我試圖讓使用std::reference_wrapper這些類的多態矢量:的std ::的reference_wrapper和多態容器

struct Int2TypeBase{ 
    virtual void which(){ std::cout << "Int2TypeBase" << "\n";} 
}; 


template <int v> 
struct Int2Type : public Int2TypeBase 
{ 
    enum 
    { 
     value = v 
    }; 

    void which(){ std::cout << "Int2Type<" << value << ">""\n";} 

    friend bool operator==(const Int2Type& lhs, const Int2Type& rhs){ 
     return lhs.v == rhs.v; 
    } 
}; 

現在我想利用std::reference_wrapper這樣的:

int main(){ 
    using namespace std; 

    std::vector<std::reference_wrapper<Int2TypeBase>> v; 

    Int2Type<0> i2t_1; 
    v.emplace_back(i2t_1); 

    auto x = v[0]; 
    x.get().which(); 

    std::cout << typeid(x.get()).name() << "\n"; 

    // std::cout << (x.get() == i2t_1) << "\n"; 
} 

輸出是:

Int2Type<0> 
8Int2TypeILi0EE 

這是我所期望的。

但是現在,當我取消std::cout << (x.get() == i2t_1) << "\n";我會得到

invalid operands to binary expression ('Int2TypeBase' and 'Int2Type<0>') 

這讓我困惑,因爲typeid(x.get()).name()返回8Int2TypeILi0EE而不是F12Int2TypeBasevE這是我得到typeid(Int2TypeBase()).name();。此外which()也被稱爲派生類...那麼爲什麼x.get()x.get() == i2t_1評估爲Int2TypeBase

回答

1

在編譯時,編譯器只能告訴x.get()的類型是Int2TypeBase,因爲如聲明的那樣,你可以在其中放置任何Int2TypeBase。所以在編譯時,它不能確定==運算符將工作。

在運行時,放入集合的對象引用它們的完整類型,所以typeid返回所期望的值,並調用正確的虛函數。

+0

有沒有另外一種方法在編譯時獲取派生對象的類型? –

+1

@lotolmencre - 不,實際上不可能。當你的集合被聲明爲持有基類型時,就編譯器而言,它可能包含任何派生類型。你想做的任何事情都是由完整類型決定的,它必須是一個虛擬方法(或者使用其他形式的動態分派) – antlersoft

2

你的比較操作只針對派生類中定義,但參考包裝生產(靜態)型Int2Base,所以重載甚至不找到的比較操作!

你可能需要的是形式

bool operator==(const Int2TypeBase& lhs, const Int2TypeBase& rhs) 

的比較操作,但那麼你還需要有某種態分派來進行實際比較,(大概假設動態類型匹配)。

相關問題