#include #include using namespace boost; /*! A is a class that does some work. Assume that it is a very fat class and we want to avoid code duplication. */ class A { public: // most of the work is generic and independent from the data types // worked on void do_something(void*) {} // would be in .cpp file really 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 thin type-safe (generic) wrapper class. Using inline functions, the idea is that the run time penalty (at least for do_something) is low. */ template class B : public A { public: void do_something(T* t) { A::do_something(t); } protected: virtual bool help_me(const T*) =0; private: bool help_me(const void* t) { return help_me(static_cast(t)); } }; struct MyStruct { }; //and finally class C : public B { bool help_me(const MyStruct* ms) { return true; } }; /* Alternatively, the class might have a callback function (object) passed that does the necessary work. */ class A2 { public: typedef boost::function helper_func; void do_something(void* t, helper_func hf) { hf(t); } }; // Helper class that provides a const void* interface and calls // Boost.Function with const T*. template struct ToVoidWrapper { typedef boost::function helper_func; helper_func hf_; ToVoidWrapper(const helper_func &hf) : hf_(hf) {} bool func(const void *t) const { return hf_(static_cast(t)); } }; /* We (ok, I) don't want the user to have to provide a callback that accepts a const void*. */ template class B2 : public A2 { public: typedef boost::function helper_func; void do_something(T* t, helper_func hf) { // just writing // A2::do_something(t, hf); // does not work: a Boost.Function that accepts a const T* is not // assignable to one that accepts a const void*. ToVoidWrapper vw(hf); A2::do_something(t, boost::bind(&ToVoidWrapper::func, &vw, _1)); } }; //and finally class C2 : public B2 { }; static bool func(const MyStruct*ms) { return true; } int main(int argc, char **argv) { C c; C2 c2; MyStruct ms; c2.do_something(&ms, func); return 0; }