templates, derived classes, and dynamic_cast

Chris Mason cmason@cmu.edu
Wed Mar 15 21:28:00 GMT 2000


Hello.

I've found something weird involving templates and dynamic_cast, and I
don't know whether it's an error in my program or a deficiency or bug in
g++.  Dynamic_casting (a base class pointer to (a template class whose
template parameter is a derived class)) into (a template class pointer
to a (template class whose template parameter is a base class)) fails. 
(See sample code below if you couldn't parse that.)

There's nothing in (the 2 Dec 1999 draft version of) the C++ std which
directly discusses dynamic_casting of templates.  So I can't say for
sure if this code is or is not correct, as far as the standard is
concerned.

I didn't dream this up.  The code is after an article by Andrew Koenig:

Koenig, Andrew.  Designing a C++ container class.  JOOP  February 1992
pg 37.

Test program (which follows, save as simpletest.cpp) outputs:

> ./simpletest
Base worked.
dynamic_cast() failed.
Derived didn't work.

Compile with:
> /usr/local/bin/g++ -Wall -o simpletest simpletest.cpp
simpletest.cpp: In function `int main(int, char **)':
simpletest.cpp:50: warning: initialization of non-const reference `class
Base *&' from rvalue `Base *'
simpletest.cpp:19: warning: in passing argument 1 of
`anyholder::put<Base *>(Base *&)'
simpletest.cpp:56: warning: initialization of non-const reference `class
Derived *&' from rvalue `Derived *'
simpletest.cpp:19: warning: in passing argument 1 of
`anyholder::put<Derived *>(Derived *&)'

This is present in snapshot 20000313:
> /usr/local/bin/g++ -v
Reading specs from /usr/local/lib/gcc-lib/i686-pc-linux-gnu/2.96/specs
gcc version 2.96 20000313 (experimental)

I don't subscribe to this list/newsgroup, so please cc any
correspondance to me.  

Thanks for a terrific, if still developing, compiler.

-c

Begin simpletest.cpp:

#include <iostream.h>


class anybase {
        public:
        virtual ~anybase() {}
};

template <class T> class any : public anybase {
        public:
        any(const T& t0) : t(t0) {}
        const T t;
};

class anyholder {
        public:
        anybase * b;
        template <class T> void put(T& val) {
                b = new any<T>(val);
        }
        template <class T> void get(T& val) {
                any<T>* a = dynamic_cast<any<T>*>(b);
                if (!a) {
                        cout << "dynamic_cast() failed.\n";
                        return;
                }
                val = a->t;
        }
        virtual ~anyholder() {}
};



class Base {
        public:
        virtual ~Base() {}
};

class Derived : public Base {
        public:
        virtual ~Derived() {}
};

int main (int argc, char ** argv) {
        anyholder * ah = new anyholder();

        Base * b = NULL;

        ah->put(new Base());
        ah->get(b);
        if (b) cout << "Base worked.\n";
        else cout << "Base didn't work.\n";

	b = NULL;
        ah->put(new Derived());
        ah->get(b);
        if (b) cout << "Derived worked.\n";
        else cout << "Derived didn't work.\n";

        return 0;
}

/* End simpletest.cpp */
/*
-- 
[ Christopher Mason        <cmason@cmu.edu>      
http://ash.rem.cmu.edu/ ]
[ "Don't you see?! We're actors--we're the opposite of people!"
-Stoppard ]
*/


More information about the Gcc-bugs mailing list