#ifndef __BLo_tabular_method_h__ #define __BLo_tabular_method_h__ // Implementation classical pattern of designing named 'tabular method'. // // example: Demonstration call function by Id, where Id may be another type. /* #include "stdafx.h" #include "BLo/tabular_method/tabular_method.h" #include class A { public: void void_int(int) { std::cout << __FUNCTION__ << std::endl; } }; const char* const_char_int_int_fn(int, int, float (*fn)(const char*)) { std::cout << __FUNCTION__ << std::endl; return "asd"; } void void_void() { std::cout << __FUNCTION__ << std::endl; } void void_int(int) { std::cout << __FUNCTION__ << std::endl; } void void_float(float) { std::cout << __FUNCTION__ << std::endl; } float float_const_char(const char*) { std::cout << __FUNCTION__ << std::endl; return 0.f; } const char* const_char_int_int(int, int) { std::cout << __FUNCTION__ << std::endl; return "asd"; } int _tmain(int argc, _TCHAR* argv[]) { BLo::tabular_method < int, void (), const char* (int, int, float (*)(const char*)), void (int), void (float), float (const char*), const char* (int, int) > asd; A a; asd.register_method(1, void_void); asd.register_method(2, void_int); asd.register_method(3, void_float); asd.register_method(4, float_const_char); asd.register_method(5, const_char_int_int); asd.register_method(6, const_char_int_int_fn); asd.register_method(7, &A::void_int, a); asd.call_method(1); asd.call_method(2, 2); asd.call_method(3, 2.f); asd.call_method(4, "asd"); asd.call_method(5, 2, 3); asd.call_method(6, 2, 3, float_const_char); asd.call_method(7, 2); return 0; } */ #include #include #include #include #include #define BTM_MAX_SIGNATURES 7 namespace BLo { namespace detail { template class base_simle_tabular_method { protected: bool empty() const // the name is a bad, but I don known bestly { return m_methods.empty(); } protected: typedef boost::function Method; typedef std::map Methods; Methods m_methods; }; template class simple_tabular_method { public: }; template class simple_tabular_method : protected base_simle_tabular_method { public: void register_method(const Id& id, R (*fn)()) { m_methods[id] = fn; } template void register_method(const Id& id, R (O::*fn)(), const O& o) { m_methods[id] = boost::bind(fn, o); } void unregister_method(const Id& id) { m_methods.erase(id); } R call_method(const Id& id) const { Methods::const_iterator i = m_methods.find(id); if (i != m_methods.end()) return (i->second)(); return R(); /*may be create policy default_return*/ } }; #define BTM_SIMPLE_TM(n) \ template \ class simple_tabular_method : protected base_simle_tabular_method \ { \ public: \ void register_method(const Id& id, R (*fn)(BOOST_PP_ENUM_BINARY_PARAMS(n, T, p))) \ { \ m_methods[id] = fn; \ } \ \ template \ void register_method(const Id& id, R (O::*fn)(BOOST_PP_ENUM_BINARY_PARAMS(n, T, p)), const O& o) \ { \ m_methods[id] = boost::bind(fn, o, BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_PP_INC(n), _)); \ } \ \ void unregister_method(const Id& id) \ { \ m_methods.erase(id); \ } \ \ R call_method(const Id& id, BOOST_PP_ENUM_BINARY_PARAMS(n, const T, & p)) const \ { \ Methods::const_iterator i = m_methods.find(id); \ \ if (i != m_methods.end()) \ return (i->second)(BOOST_PP_ENUM_PARAMS(n, p)); \ \ return R(); /*may be create policy default_return*/ \ } \ }; #define BTM_ALL_SIMPLE_TM(z, n, text) BTM_SIMPLE_TM(n) BOOST_PP_REPEAT_FROM_TO(1, BOOST_FUNCTION_MAX_ARGS, BTM_ALL_SIMPLE_TM, BOOST_PP_EMPTY) #undef BTM_ALL_SIMPLE_TM #undef BTM_SIMPLE_TM } template class tabular_method { public: }; #define BTM_INHERIT_SIMPLE_TM(z, n, text) \ protected detail::simple_tabular_method #define BTM_USING_SIMPLE_TM(z, n, text) \ using detail::simple_tabular_method::register_method; \ using detail::simple_tabular_method::call_method; \ using detail::simple_tabular_method::unregister_method; #define BTM_EMPTY(z, n, text) \ && detail::simple_tabular_method::empty() #define BTM_TABULAR_METHOD(n) \ template \ class tabular_method \ : BOOST_PP_ENUM(n, BTM_INHERIT_SIMPLE_TM, BOOST_PP_EMPTY) \ { \ public: \ BOOST_PP_REPEAT(n, BTM_USING_SIMPLE_TM, BOOST_PP_EMPTY) \ bool empty() const \ { \ return true BOOST_PP_REPEAT(n, BTM_EMPTY, BOOST_PP_EMPTY()); \ } \ }; #define BTM_ALL_TABULAR_METHOD(z, n, text) BTM_TABULAR_METHOD(n) BOOST_PP_REPEAT_FROM_TO(1, BTM_MAX_SIGNATURES, BTM_ALL_TABULAR_METHOD, BOOST_PP_EMPTY) #undef BTM_ALL_TABULAR_METHOD #undef BTM_TABULAR_METHOD #undef BTM_USING_SIMPLE_TM #undef BTM_USING_SIMPLE_TM } #endif // __BLo_tabular_method_h__