[MPL] Need help crossing runtime boundary (lengthy)
Hi all, I'm new to using the MPL and I want to write a generic class, that makes it easy to provide other classes with a mechanism to notify their clients about member changes. I'll paste in some code that illustrates how I imagine this thing could look like. I've marked three places with comments ((1), (2), (3)) that contain the specific questions but I also welcome more general suggestions. For example I'd appreciate alternatives to the std::map within the Notifier. <code> template <class OBJECT_TYPE, typename MEMBER_ID_TYPE, typename ID_TO_MEMBER_MAP_TYPE> class Notifier { // an alternative combiner for signals struct notifier_combiner { typedef boost::optional< int > result_type; template <typename INPUT_ITERATOR> result_type operator()(INPUT_ITERATOR pFirst, INPUT_ITERATOR pLast) const { result_type res; for (; pFirst != pLast; ++pFirst) res = *pFirst; return res; } }; template <MEMBER_ID_TYPE id, typename MEMBER_TYPE> struct get_signal_type { typedef boost::signal< int (OBJECT_TYPE const*, MEMBER_TYPE const&), notifier_combiner > type; }; // (1) How can I get SOMETHING? It should be a sequence of all // possible signal types, most probably an mpl::set, so that each // signal type is only present once. I guess I should iterate // over the elements in ID_TO_MEMBER_MAP_TYPE and then call // get_signal_type< elem::first::value, elem::second::type >, but // I don't see exactly how to use one of the mpl-algorithms or // generic iteration. typedef boost::make_variant_over< SOMETHING >::type signals_t; // maps member ids to a variant containing the 'right' signal type typedef std::map< MEMBER_ID_TYPE, signals_t > signal_map_t; signal_map_t signal_map; public: Notifier() { // (2) How do I initialise signal_map so that all ids map to a // signals_t instance with the right default constructed // signal type assigned? I guess the answer is somewhere in // chapter 9 of "C++ template metaprogramming" but that's the // chapter that is the hardest one to grasp for me :-) } template <MEMBER_ID_TYPE id, typename MEMBER_TYPE> boost::connection connect(get_signal_type< id, MEMBER_TYPE >::type::slot_type slot) { return boost::get< get_signal_type< id, MEMBER_TYPE >::type >(signal_map[id]).connect(slot); } template <MEMBER_ID_TYPE id, typename MEMBER_TYPE> int notify(OBJECT_TYPE const *pObj, MEMBER_TYPE const &member_val) const { boost::optional< int > res = boost::get< get_signal_type< id, MEMBER_TYPE >::type >(signal_map[id])(pObj, member_val); return res ? res.get() : 0; } }; // how I'd like to use it: strcut sth_ { int i; long j; } class RandomClass { bool yesno; sth_ sth; enum MemberId { YESNO , STH }; typedef mpl::map< mpl::pair< mpl::integral_c< MemberId, YESNO >, bool > , mpl::pair< mpl::integral_c< MemberId, STH >, sth_ > > id_to_member_type_t; template < typename INTEGRAL_CONST > struct get_type_by_id { typedef mpl::at< id_to_member_type_t, INTEGRAL_CONST >::type type; }; Notifier< RandomClass // I hope incomplete type is ok here // (because Notifier only uses // RandomClass const*; OTOH, Notifier // uses a std::map which somehow // refers to RandomClass)? Anyway, // this is not crucial. , MemberId , mpl::map< mpl::pair< mpl::integral_c< MemberId, YESNO >, bool > , mpl::pair< mpl::integral_c< MemberId, YESNO >, sth_ > > > m_notifier; public: RandomClass() : yesno(false) , sth({1, 2}) { } // a client connects by specifying the member id and a callback template < MemberId id > boost::connection notify(int (pF*)(RandomClass const* , get_type_by_id< mpl::integral_c< MemberId, id > >::type const&)) { // (3) Can the compiler deduce the second template argument of // Notifier::connect? I guess not, so how could I change the // method's declaration to make that happen? return m_notifier.connect< id >(pF); } void setYesNo(bool b) { yesno = b; m_notifier<YESNO>(this, b); } void setSthI(int i) { sth.i = i; m_notifier<STH>(this, sth); } }; </code> Obviously this doesn't yet compile and there may be all sorts of errors. I hope that's ok, because I still need very basic help. TIA, aa -- Andreas Ames | Programmer | Comergo GmbH | Voice: +49 69 7505 3213 | andreas . ames AT comergo . com "I imagine Sisiphus as happy ..." Albert Camus
participants (1)
-
Ames Andreas