views:

164

answers:

3

The following code is a simplified version of what I use for event dispatching. The essential point is that there is a static_cast<T*> on the argument of a template functor and another class makes sure that the argument passed to the functor is what the static_cast casts to.

struct AbstractArg {
  virtual ~AbstractArg() { }
};

struct AbstractFunctor {
  virtual void operator()(AbstractArg*) const = 0;
  virtual ~AbstractFunctor() { }
};


namespace evil {

template<typename ArgT>
struct CastingFunctor :  AbstractFunctor {
  void operator()(AbstractArg* aarg) const
  {
    ArgT* arg = static_cast<ArgT*>(arg); // Danger!
    // ... do stuff with it
  }
};

} // namespace evil


class TypeidManager
{
public:
  typedef std::map<std::string, AbstractFunctor*> map_type;

  void dispatch(AbstractArg* arg) const
  {
    map_type::const_iterator it = typeid_map.find(std::string(typeid(*arg).name()));
    if (it != typeid_map.end())
    {
      AbstractFunctor* pFunctor = it->second;
      (*pFunctor)(arg);
    }
  };

  template<typename ArgT>
  void register_func( void (*fun_ptr)(ArgT*))
  {
    typeid_map.insert(std::make_pair(std::string(typeid(ArgT).name()),
                                     new evil::CastingFunctor<ArgT>));
  }

private:
  map_type typeid_map;
};

Is there a name for this pattern?

Thanks!

A: 

Not that I know of, although we use something similar here.

bltxd
+1  A: 

I think it is an anti-pattern, not a pattern. Normally the things you want to feed to the functors via the typeid_map construct would come from a common inheritance hierarchy and you would use dynamic polymorphism (= virtual methods) instead. Basically you have reinvented virtual method table lookup (in a very inefficient manner).

antti.huima
I mostly agree, the pattern is borderline but it has its use. Its main advantage being that you don't force any interface/inheritance on client classes.
bltxd
This is a good pattern. Used by such libs as boost::function, boost::any and loads of others. As the other answer says, this is called type-erasure. What can be bad is abuse of it. Like you can abuse the visitor-pattern, you can abuse this pattern. Here is an article about an any-container: http://www.two-sdg.demon.co.uk/curbralan/papers/ValuedConversions.pdf
Johannes Schaub - litb
Thank you, litb
Maik Beckmann
might be worth pointing out though, that boost has an any-container you can use (as well as variant for bounded types), so you can usually avoid implementing type erasure yourself.
jalf
+2  A: 

This isn't an anti-pattern, it's a really useful technique often used with type erasure.

Reading what litb wrote, I think "Type Erasure" is the name of the pattern/technique. Since I cannot mark his comment and he refers to your answer my kudos goes to you :)
Maik Beckmann
:) This looks like a good read: http://www.artima.com/cppsource/type_erasure.html
Johannes Schaub - litb