标准::reference_wrapper和多态容器

std::reference_wrapper and polymorphic containers

本文关键字:多态 wrapper reference 标准      更新时间:2023-10-16

我正在尝试使用这些类使用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呢?

您的比较运算符仅针对派生类定义,但引用包装器生成(静态)类型Int2Base,因此重载分辨率甚至找不到您的比较运算符!

您可能需要的是表单的比较运算符

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

但是,您还需要进行某种多态调度来执行实际比较(大概假设动态类型匹配)。

在编译时,编译器只能告诉 x.get() 的类型是 Int2TypeBase,因为正如声明的那样,您可以将任何 Int2TypeBase 放在那里。 因此,在编译时,它无法确定 == 运算符是否有效。

在运行时,放入集合中的对象引用其完整类型,因此 typeid 返回您期望的内容并调用正确的虚函数。