Boost logo

Boost Users :

Subject: [Boost-users] [partly: Boost.Function] typesafe (templated) wrapper around class with void* API
From: Christoph Duelli (duelli_at_[hidden])
Date: 2009-01-29 03:20:37


[This question has a Boost.Function relation later on.
Sorry if too off topic.]

I have a class that works on some data structures.
This class' API uses void* to be general and avoid
code duplication that using a template here would incur.

Basically:

class A // simplification
{
   // Assume A to be a "fat" class there are more methods
   // working on void*
   // and lots of code put away into a .cpp file. We don't
   // want that duplicated by many template instantiations.
public:
   // Most of the work is generic and independent from the
   // data types worked on.
   void do_something(void*);
protected:
   // some work has to be done be the subclass
   virtual bool help_me(const void*) =0;
};

I do not like using void* all that much. Thus I would like
to create a type-safe (generic) thin wrapper class. Using
inline functions,the idea is that the run time penalty (at
least for do_something) is low and casts from/and to void
are all 'hidden' here.

template<typename T>
class B : public A
{
public:
   void do_something(T* t) { A::do_something(t); }
protected:
   // Force user to provide a correctly typed callback.
   virtual bool help_me(const T*) =0;
private:
   // call the user's safe callback
   bool help_me(const void* t)
   {
      return help_me(static_cast<const T*>(t));
   }
};

and finally
class C : public B<MyStruct>
{
   bool help_me(const MyStruct* ms) { ... }
};

Is this a good way to do that?

More specific questions:
i) I assume the penalty for my callback "help_me" is one
more indirection. Can't see that optimized away.

ii) Assuming A's interface gets passed a real callback
function (a Boost.Function) instead:

class A
{
public:
   typedef boost::function<bool(const void*)> helper_func;
   void do_something(void*, helper_func);
};

is it somehow possible to get a typesafe templated B such that
template<typename T>
class B : public A
{
public:
   typedef boost::function<bool(const T*)> helper_func;
   void do_something(T* t, helper_func hf)
   {
      // this makes my compiler unhappy (when instanced).
      // I do understand that... can it be worked around somehow?
      A::do_something(t, hf);
   }
};

I would like to be able to pass a function working on T*
rather than void*.

While writing this posting have found the following to compile:
template<typename T>
struct ToVoidWrapper
{
   typedef boost::function<bool(const T*)> helper_func;
   helper_func hf_;
   ToVoidWrapper(const helper_func &hf) : hf_(hf) {}
   bool func(const void *t) const
      { return hf_(static_cast<const T*>(t)); }
};
with do_something in B:
  void do_something(T* t, helper_func hf)
   {
      ToVoidWrapper<T> vw(hf);
      A2::do_something(t,
                       boost::bind(&ToVoidWrapper<T>::func, &vw, _1));
   }

I am not really looking forward to writing such
"forwarding to void*" functions. Are there alternatives?
Maybe something in Boost that I have overlooked?
Or a standard C++ idiom I am not aware of?

I have attached compilable code that sums up the
above code snippets so far.

Thank you for looking into this and best regards
Christoph



Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net