Dynamic task and auto

When using auto and dynamic_cast, I came across a rather strange behavior. This is the hierachy class I have:

class BaseInterface { public: virtual void someMethod()=0; }; class Derived:public BaseInterface { public: virtual void someMethod1()=0; void someMethod()override; }; 

And, of course, there are some classes that implement all derived methods.

Then there is a third class that looks like this:

 class ThirdClass { public: void demoMethod(BaseInterface&); void anotherMethod(Derived&); }; void ThirdClass::demoMethod(BaseInterface& obj) { auto buffer=dynamic_cast<Derived&>(obj); anotherMethod(buffer); } 

When I compile this with gcc, I get the error "cannot select object of abstract type". If i replace

 auto buffer=... 

with

 Derived& buffer=... 

everything compiles fine. Why is this so? Doesn't automatically output the correct type or something else?

I also found a dirty trick that still uses auto:

 void ThirdClass::demoMethod(Base& obj) { auto buffer=dynamic_cast<Derived*>(&obj); anotherMethod(*buffer); } 
+5
source share
2 answers

You get Derived from auto . Use this instead:

 auto & buffer = dynamic_cast<Derived&>(obj); 
+6
source

Β§7.1.6.4 / 7:

When a variable declared using the placeholder type, the output type [...] returned is initialized or the type of the variable is determined by the type of its initializer. [...] let T is the declared type of the variable or the return type of the function. If the placeholder is auto type-specifier, the type being deduced is determined using the rules to output the template argument. [...] get P from T by replacing the occurrences of auto or using the new template type parameter U [...]. Derive a value for U using the template rules to derive an argument from a function call (14.8.2.1), where P is the type of the function template parameter, and the corresponding argument is the initializer.

So, to familiarize yourself with the process, take a look at the actual rule used to output the buffer type: what happens if you change

 template <typename U> void f( U ); 

to

 void f( Derived& ); 

when calling f with an lvalue of type Derived ? Obviously, for the function template, U will be displayed as Derived , which will then fail.
This directly matches the placeholder type deduction in your example - auto will be replaced with Derived , and this will not work, since Derived is abstract.

Generally speaking, if you write

 auto obj = …; 

obj will never be a reference , since U will never be inferred as a reference type when calling the above function template.


Use auto& instead:

 auto& buffer = dynamic_cast<Derived&>(obj); 

Now P is U& :

 template <typename U> void f(U&); 

U , of course, is still output as Derived , but the type P - which is actually the buffer type - Derived& .

+5
source

All Articles