2017-02-24 27 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) 

的比较操作,但那么你还需要有某种态分派来进行实际比较,(大概假设动态类型匹配)。

相关问题