I am trying to make a polymorphic vector using std::reference_wrapper
for these classes:
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;
}
};
Now I am trying to make use of std::reference_wrapper
like this:
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";
}
The output is:
Int2Type<0>
8Int2TypeILi0EE
This is what I would expect.
Now however, when I uncomment std::cout << (x.get() == i2t_1) << "\n";
I will get
invalid operands to binary expression ('Int2TypeBase' and 'Int2Type<0>')
This confuses me, as typeid(x.get()).name()
returned 8Int2TypeILi0EE
rather than F12Int2TypeBasevE
which is what I get for typeid(Int2TypeBase()).name();
. Furthermore which()
also was called for the derived class... so then why does x.get()
in x.get() == i2t_1
evaluate to a Int2TypeBase
?
Your comparison operator is only defined for derived classes, but the reference wrapper produces (static) type
Int2Base
, so overload resolution does not even find your comparison operator!What you probably need is a comparison operator of the form
but then you also need to have some sort of polymorphic dispatch to perform the actual comparison (presumably assuming that the dynamic types match).
At compile time, the compiler can only tell that the type of x.get() is Int2TypeBase, because as declared you can put any Int2TypeBase there. So at compile time, it can't determine that the == operator will work.
At run time, the objects you put in the collection reference their full type, so typeid returns what you expect and the correct virtual function is called.