I am playing around with the auto feature in the C++0X standard but I am confused how the decision of the type is made. Consider the following code.
struct Base
{
virtual void f()
{
std::cout << "Base::f" << std::endl;
}
};
struct Derived : public Base
{
virtual void f()
{
std::cout << "Derived::f" << std::endl;
}
};
int main()
{
Base* dp = new Derived;
auto b1 = *dp;
auto& b2 = *dp;
std::cout << typeid(b1).name() << std::endl;
std::cout << typeid(b2).name() << std::endl;
}
It will print Base and Derived.
But why is the auto&
evaluated to a ref to Derived and not to a ref to Base?
Even worse changing the code to this:
struct Base{};
struct Derived : public Base{};
int main()
{
Base* dp = new Derived;
auto b1 = *dp;
auto& b2 = *dp;
std::cout << typeid(b1).name() << std::endl;
std::cout << typeid(b2).name() << std::endl;
}
returns Base for both types. So why is the type depended on the virtual functions? The compiler I am using is VS2010. Can anyone give me a hint where I can find the definition of this behavior in the standard?
auto
in both contexts is yielding Base
, not derived. In the first case you are slicing the object (copy at the parent level) while in the second case, because it is a reference, you get a Base&
to the actual Derived
object. That means that all virtual function calls will be dispatched to the final overrider at the Derived
level.
The typeid
operator has different behavior for polymorphic types than for non-polymorphic ones. If applied to a reference to a polymorphic type it will perform a type check at runtime and yield the type of the actual object. If it is applied to an object or to a reference to a non-polymorphic type it will be resolved at compile time to the static type of the object or reference.
To verify what the auto
is inferring, you can use a slightly different test:
void test( Base& ) { std::cout << "Base" << std::endl; }
void test( Derived& ) { std::cout << "Derived" << std::endl; }
Then call the function and see what type it is resolving to. I would expect the compiler to pick the first overload, as auto& a = *dp;
should be equivalent to Base& a = *dp;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With