Boost logo

Boost Users :

From: David Abrahams (dave_at_[hidden])
Date: 2005-05-01 10:01:25

"Delfin Rojas" <drojas_at_[hidden]> writes:

>> Not knowing what type of Foo it holds, how would you know what to do
>> with the result of getP? Its type depends on the type of the Foo.
> Yes, what I do with the result of getP would depend on the type of U. That
> is why I would need to get the right Foo<> back from FooBase *. Then I would
> pass this Foo<> through a template function that is specialized to a
> specific U and knows what to do with the result of getP().

In that case you're erasing the type information too early. You need
to instantiate the function template you mention above (call it f)
before you lose the type of Foo, e.g. make a vector of

  template <class T> void f(T*);

  struct FooHolderBase
      virtual ~FooHolderBase() {}
      virtual void do_something_with_getP() = 0;

  template <class U>
  struct FooHolder
      FooHolder(Foo<U> const& x) : held(x) {}

      void do_something_with_getP()
          f(held.getP()); // <== f gets instantiated

      Foo<U> held;

  template <class U>
  void add_foo(
     std::vector<boost::shared_ptr<FooHolderBase> > v
   , Foo<U> const& x
         shared_ptr<FooHolderBase>(new FooHolder<U>(x))

There are various other ways to write this basic idiom (e.g. using
function pointers instead of building a class with virtual functions),
but the essential thing is that f<U> gets instantiated when you still
know U at compile-time.

If you try to erase the type first, you will end up with what is
essentially a massive type-switch:

     type_info dynamic_type = typeid(*some_foo_base_ptr);
     if (dynamic_type == typeid(Foo<A>))
     else if (dynamic_type == typeid(Foo<B>))

which really sucks because it has to be maintained every time you
write Foo<U> for some new U.


Dave Abrahams
Boost Consulting

Boost-users list run by williamkempf at, kalb at, bjorn.karlsson at, gregod at, wekempf at