c++ template casting with derived classes
-
22-09-2019 - |
Question
#include <vector>
struct A {int a;};
struct B : public A {char b;};
int main()
{
B b;
typedef std::pair<A*, A*> MyPair;
std::vector<MyPair> v;
v.push_back(std::make_pair(&b, &b)); //compiler error should be here(pair<B*,B*>)
return 0;
}
I don't understand why this compiles (maybe somebody can kindly provide detailed explanation? Is it something related to name look-up?
Btw, on Solaris, SunStudio12 it doesn't compile: error : formal argument x of type const std::pair<A*, A*> & in call to std::vector<std::pair<A*,A*> >::push_back(const std::pair<A*, A*> & ) is being passed std::pair<B*, B*>
Solution
std::pair
has a constructor template:
template<class U, class V> pair(const pair<U, V> &p);
"Effects: Initializes members from the corresponding members of the argument, performing implicit conversions as needed." (C++03, 20.2.2/4)
Conversion from a derived class pointer to a base class pointer is implicit.
OTHER TIPS
Because B is derived from A, the vector v will contain pointers to base class structures of the object b. therefore, you could access the members of A, i.e.
std::cout << v[0].first->a;
EDIT: My mistake, as pointed out below, you can still cast to pointers of type B since the vector is of pointers, not objects, so no object slicing has occurred.
A call such as
std::cout << v[0].first->b;
will not compile since the elements in the vector are base class pointers and cannot point to derived class members without a cast, i.e.
std::cout << static_cast<B*>(v[0].first)->b;
Also note that a dynamic cast, as in
std::cout << dynamic_cast<B*>(v[0].first)->b;
will not compile with the following error in gcc:
cast.cpp:14: error: cannot dynamic_cast ‘v.std::vector<_Tp, _Alloc>::operator[] [with _Tp = std::pair<A*, A*>, _Alloc = std::allocator<std::pair<A*, A*> >](0u)->std::pair<A*, A*>::first’ (of type struct A*’) to type struct B*’ (source type is not polymorphic)