6

I've encountered a pretty weird behavior when using auto and dynamic_cast. This is the class hierachy 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 which 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 an "cannot allocate an object of abstract type" error. Whereas when i replace

auto buffer=...

with

Derived& buffer=...

everything compiles fine. Why is that the case? Is auto not deducing the right type or something?

Also i found a dirty trick to still use auto:

void ThirdClass::demoMethod(Base& obj) {
    auto buffer=dynamic_cast<Derived*>(&obj);
    anotherMethod(*buffer);
}
Bill Lynch
  • 80,138
  • 16
  • 128
  • 173
  • 4
    I'm guessing `auto` deduces the type `Derived buffer`, not `Derived& buffer`. – melpomene Jul 25 '15 at 16:02
  • What version of g++ are you using? Works fine to compile your code [after fixing trivial typos such as no return type on `demoMethod` and no inheritance on `derived`] - both clang++ 3.7 (about two weeks old) and g++ 4.9.2. – Mats Petersson Jul 25 '15 at 16:04
  • @MatsPetersson: If the missing return type is fixed, it fails in the reported way with whatever compiler ideone uses: http://ideone.com/UEtfui – Bill Lynch Jul 25 '15 at 16:12
  • 1
    @BillLynch: Always nice when the code changes between you trying it out and the next person trying it... ;) – Mats Petersson Jul 25 '15 at 16:20
  • @BillLynch: FYI, hover over "C++14" to see what compiler it uses (for the record, at time of writing it's GCC 4.9.2). – Lightness Races in Orbit Jul 25 '15 at 16:22
  • @BillLynch Use Coliru or Wandbox instead. Ideone is inferior to those in every respect. – Columbo Jul 25 '15 at 16:33

2 Answers2

6

You're getting Derived from auto. Use this instead:

auto & buffer = dynamic_cast<Derived&>(obj);
Bill Lynch
  • 80,138
  • 16
  • 128
  • 173
4

§7.1.6.4/7:

When a variable declared using a placeholder type is initialized […] the deduced return type or variable type is determined from the type of its initializer. […] let T be the declared type of the variable or return type of the function. If the placeholder is the auto type-specifier, the deduced type is determined using the rules for template argument deduction. […] obtain P from T by replacing the occurrences of auto with either a new invented type template parameter U[…]. Deduce a value for U using the rules of template argument deduction from a function call (14.8.2.1), where P is a function template parameter type and the corresponding argument is the initializer.

So, in order to familiarize yourself with the process, take a look at the actual rule used for deducing the type of buffer: What happens if you change

template <typename U>
void f( U );

to

void f( Derived& );

when calling f with an lvalue of type Derived? Clearly, for the function template, U will be deduced as Derived, which then yields a deduction failure.
This directly corresponds to the deduction of the placeholder type in your example - auto will be replaced by Derived, and that fails, as Derived is abstract.

Generally speaking, if you write

auto obj = …;

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


Instead, use auto&:

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

Now, P is U&:

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

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

Columbo
  • 60,038
  • 8
  • 155
  • 203
  • @LightnessRacesinOrbit Well, I figured that the asker is used to template argument deduction :) – Columbo Jul 25 '15 at 16:23
  • @Columbo To be honest im not. I just started with c++ like 3 months ago and havent stumbled over templates yet. –  Jul 25 '15 at 16:28
  • 1
    @SuppenGeist In that case, nevermind. Maybe someone else will find this answer useful. – Columbo Jul 25 '15 at 16:30