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
?
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.