factory method across shared lib not working for templated derived class

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Dear List Members

I have distilled a problem I have been having to the following code example. I
have tried to make it as compact as possible, and I apologize that it is still
rather long.

In essence, a polymorphic pointer to a base class that is returned from a
factory function in a shared library cannot be cast to its derived type using
dynamic_cast iff the derived type was templated:

--tlib.hh--

#ifndef TLIB_H
#define TLIB_H

class Base {
public:
  virtual void A() = 0;
};

template <typename X>
class DerivedOne: public Base {
public:
  virtual void A();
};

typedef DerivedOne<int> DerivedOneInt;

class DerivedTwo: public Base {
public:
  virtual void A();
};

Base* CreateOne(); // will create DerivedOneInt
Base* CreateTwo(); // will create DerivedTwo

#endif
----

--tlib.cc--

#include "tlib.hh"

template<typename X>
void DerivedOne<X>::A()
{
}

void DerivedTwo::A()
{
}

Base* CreateOne()
{
  return new DerivedOneInt();
}

Base* CreateTwo()
{
  return new DerivedTwo();
}

// explicit instantiation
template class DerivedOne<int>;

----

This is compiled into a library using
g++ -shared tlib.cc -o libt.so

Now comes the example code that demonstrates the problem:

--tmain.cc--

#include <iostream>
#include "tlib.hh"

int main()
{
  //derived one
  Base* bp_one_a = CreateOne();
  DerivedOneInt* dp_one_a = dynamic_cast<DerivedOneInt*>(bp_one_a); // fails
  std::cerr << "bp_one_a=" << bp_one_a << " dp_one_a=" << dp_one_a << std::endl;

  Base* bp_one_b = new DerivedOneInt();
  DerivedOneInt* dp_one_b = dynamic_cast<DerivedOneInt*>(bp_one_b); // works
  std::cerr << "bp_one_b=" << bp_one_b << " dp_one_b=" << dp_one_b << std::endl;

  //prints false
  std::cerr << (typeid(*bp_one_a)==(typeid(*bp_one_b)) ? "true" : "false") <<
std::endl;

  // derived two
  Base* bp_two_a = CreateTwo();
  DerivedTwo* dp_two_a = dynamic_cast<DerivedTwo*>(bp_two_a); // works
  std::cerr << "bp_two_a=" << bp_two_a << " dp_two_a=" << dp_two_a << std::endl;

  Base* bp_two_b = new DerivedTwo();
  DerivedTwo* dp_two_b = dynamic_cast<DerivedTwo*>(bp_two_b); // works
  std::cerr << "bp_two_b=" << bp_two_b << " dp_two_b=" << dp_two_b << std::endl;

  // prints true
  std::cerr << (typeid(*bp_two_a)==(typeid(*bp_two_b)) ? "true" : "false") <<
std::endl;

  return 0;
}
----
which is compiled using
g++ tmain.cc -o tmain -L /PATH/TO/LIB -l t


The dynamic_cast of 'bp_one_a' to 'dp_one_a' fails, while all others work fine.
Also, the first typeid comparison is false, while the second one is true. I
suspect this is where the problem really is...

Any help would be greatly appreciated. This is gcc version 4.0.1 (4.0.1-0.2mdk
for Mandriva Linux release 2006.0)

Cheers - Ansgar

========================================
Ansgar Philippsen, PhD
MIH - Biozentrum - Basel - Switzerland
http://www.mih.unibas.ch
----------------------------------------
nobody is equal, everybody is equivalent
----------------------------------------


----------------------------------------------------------------
This message was sent using IMP, the Internet Messaging Program.


[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux