
Hi, I like the idea behind the Interfaces Library: http://www.kangaroologic.com/interfaces/ I need one now. I dislike the macro-based Interface Definition Language, however. I find it utterly ugly especially because interfaces should be immediately readable. IMO, the macro-based IDL is not. Here's another take (prototype) at a macro less implementation of the interfaces (see attached). Tested on VC7.1, g++ and Comeau. The biggest advantage is that the same C++ member function interface syntax is retained. This makes it very easy to understand and even allows documentation extraction tools like Doxygen to work as usual. A disadvantage is that there is some unavoidable redundancy-- a lesser price to pay, IMO. Here's a client side example: struct foo : member_function<int(int)> {}; struct bar : member_function<int(char const*)> {}; // a baz "interface" class baz : interface<foo, bar> { public: template <class T> baz(T& x) : construct(x) {} int foo(int x) { return this->call< ::foo>(x); } int bar(char const* x) { return this->call< ::bar>(x); } }; struct some_baz { int impl(foo, int x) { return x + 1; } int impl(bar, char const* s) { return std::strlen(s); } }; struct another_baz { int impl(foo, int x) { return x - 1; } int impl(bar, char const* s) { return -std::strlen(s); } }; int main() { some_baz f; baz p = f; std::cout << "p.foo(3) = " << p.foo(3) << std::endl; std::cout << "p.bar(\"hi\") = " << p.bar("hi") << std::endl; another_baz f2; p = f2; std::cout << "p.foo(3) = " << p.foo(3) << std::endl; std::cout << "p.bar(\"hi\") = " << p.bar("hi") << std::endl; } Regards, -- Joel de Guzman http://www.boost-consulting.com http://spirit.sf.net #include <iostream> #include <string> #include <cstring> #include <boost/spirit/fusion/sequence/tuple.hpp> #include <boost/spirit/fusion/sequence/at.hpp> using namespace boost::fusion; template <class Sig> struct member_function; template <class RT, class A0> struct member_function<RT(A0)> { typedef RT return_type; typedef A0 arg0_type; typedef RT(*pointer_type)(void*, A0); }; template <class F0, class F1> struct interface { typedef tuple< typename F0::pointer_type , typename F1::pointer_type> vtable_type; template <class T> struct functions { template <typename F> struct forward { typedef typename F::return_type return_type; typedef typename F::arg0_type arg0_type; static return_type call(void* p, arg0_type x) { return static_cast<T*>(p)->impl(F(), x); } }; static typename interface<F0, F1>::vtable_type const* table() { static typename interface<F0, F1>::vtable_type vtable( &forward<F0>::call , &forward<F1>::call); return &vtable; // a singleton } }; template <class T> interface(T& x) : vtable(functions<T>::table()) , obj(&x) {} typedef interface<F0, F1> construct; typename boost::fusion::meta::at_c<vtable_type const, 0>::type find(F0) const { return boost::fusion::at<0>(*vtable); } typename boost::fusion::meta::at_c<vtable_type const, 1>::type find(F1) const { return boost::fusion::at<1>(*vtable); } template <typename F> typename F::return_type call(typename F::arg0_type x) { return find(F())(const_cast<void*>(obj), x); } vtable_type const* vtable; void const* obj; }; /////////////////////////////////////////////////////////////// // // Client Code // /////////////////////////////////////////////////////////////// struct foo : member_function<int(int)> {}; struct bar : member_function<int(char const*)> {}; // a baz "interface" class baz : interface<foo, bar> { public: template <class T> baz(T& x) : construct(x) {} int foo(int x) { return this->call< ::foo>(x); } int bar(char const* x) { return this->call< ::bar>(x); } }; struct some_baz { int impl(foo, int x) { return x + 1; } int impl(bar, char const* s) { return std::strlen(s); } }; struct another_baz { int impl(foo, int x) { return x - 1; } int impl(bar, char const* s) { return -std::strlen(s); } }; int main() { some_baz f; baz p = f; std::cout << "p.foo(3) = " << p.foo(3) << std::endl; std::cout << "p.bar(\"hi\") = " << p.bar("hi") << std::endl; another_baz f2; p = f2; std::cout << "p.foo(3) = " << p.foo(3) << std::endl; std::cout << "p.bar(\"hi\") = " << p.bar("hi") << std::endl; }