
Peter Dimov wrote:
Marcus Lindblom wrote:
I can only add that I've found myself lacking this as well. (My workaround is to pass a boost::function type as well, to get the signature info. Not nice, but works.) Can you please show some use cases for this? I have my own c++ <-> xml bind system that binds directly to member functions, but also to generic function objects.
It allows syntax like: ScriptClassImpl<Foo>.attr("my_attribute").bind(&Foo::bar); ScriptClassImpl<Foo>.element("my_element").bind(&Foo::baz, "arg_1", "arg_2"); ScriptClassImpl<Foo>.attr("my_attribute") = my_free_function; // (my_free_function takes Foo* and xml-node) In the bind()-cases, it uses mem_fn to call the actual function: template<class C> template<class T, typename A1, typename A2> void ScriptClassImpl<C>::ElemBinder::bind(void (T::*f)(A1, A2), const char* n1, const char* n2) { BOOST_STATIC_ASSERT((::boost::is_base_and_derived<T, C>::value||::boost::is_same<T, C>::value)); typedef boost::function<void (T&, A1, A2)> func_type; *m_f = xml::mkApplyElemFunctor<func_type>(boost::mem_fn(f), *m_log).arg(n1).arg(n2); } I'd like to avoid the use of func_type here, it's just a type-info carrier. (I could probably use a mpl::list or something with less baggage) ApplyElemFunctor translates xml into an actual function call, in it's operator(): template<class BF, typename F> class ApplyElemFunctor : public ApplyElemFunctorStore { public: typedef typename boost::remove_reference<typename BF::arg1_type>::type obj_type; ApplyElemFunctor(base::Logger& log, F& f); /// catches and reports any errors when invoking function bool operator () (obj_type& obj, const xmlNodePtr& in, xmlNodePtr& out); private: // do-call is specialized for each arity (1 to 5 at the moment) template<> void doCall<3>(obj_type& obj, const xmlNodePtr& in, xmlNodePtr& out) ... }; template<class BF, class F> bool ApplyElemFunctor<BF, F>::operator () (obj_type& obj, const xmlNodePtr& in, xmlNodePtr& out) { try { doCall<BF::arity>(obj, in, out); return true; } catch(internal::XMLArgFailed &e) { e.report(in, out, m_log); return false; } } template<class BF, class F> template<> void ApplyElemFunctor<BF, F>::doCall<3>(obj_type& obj, const xmlNodePtr& in, xmlNodePtr& out) { typedef internal::arg_type<BF::arg2_type>::type a1; typedef internal::arg_type<BF::arg3_type>::type a2; m_f(obj, getAttr<a1>(in, 0), getAttr<a2>(in, 1)); } So, doCall() is where I have to use BF (boost::function) rather than F (boost::mem_fn) since mem_fn doesn't expose it's arg-types or arity. (getAttr<> does argument name lookup & lexical_cast to type, or object-lookup if it's a pointer type) There might be a better way to do all this, as it is my first attempt at c++ language binding after all. But it has worked remarkably well for the last 1.5 years in service. :) Cheers, /Marcus