//============================ // Project: Open Code Foundation Classes (OCFC) // Version: 1.0.0 // File: class_factory.hpp // Written by Nabla // Copyright @ 2005 Nabla. All rights reserved. //============================ // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #ifndef OCFCSENTRY_CLASS_FACTORY_HPP # define OCFCSENTRY_CLASS_FACTORY_HPP #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace ocfc { //============================ // Implement class_factory_implementationN // this class actually create an instance of a class using its constructor member function with N parameters //============================ class CLSIMPEXP_OCFC class_factory_implementation0 { public: inline class_factory_implementation0() NO_THROW {} inline ~class_factory_implementation0() NO_THROW {} template _C* create_instance() const { return new _C; } }; template class class_factory_implementation1 { private: _A1 __m_a1; public: explicit class_factory_implementation1(_A1 __a1) NO_THROW : __m_a1(__a1) {} inline ~class_factory_implementation1() NO_THROW {} template _C* create_instance() const { return new _C(__m_a1); } }; template class class_factory_implementation2 { private: _A1 __m_a1; _A2 __m_a2; public: inline class_factory_implementation2(_A1 __a1, _A2 __a2) NO_THROW : __m_a1(__a1), __m_a2(__a2) {} inline ~class_factory_implementation2() NO_THROW {} template _C* create_instance() const { return new _C(__m_a1, __m_a2); } }; template class class_factory_implementation3 { private: _A1 __m_a1; _A2 __m_a2; _A2 __m_a3; public: inline class_factory_implementation3(_A1 __a1, _A2 __a2, _A3 __a3) NO_THROW : __m_a1(__a1), __m_a2(__a2), __m_a3(__a3) {} inline ~class_factory_implementation3() NO_THROW {} template _C* create_instance() const { return new _C(__m_a1, __m_a2, __m_a3); } }; template struct class_factory_implementation_chooser { typedef typename boost::mpl::vector<_A1, _A2, _A3> params_t; typedef typename boost::mpl::size::type index_t; // 0...N-1 typedef typename boost::mpl::vector< class_factory_implementation0, class_factory_implementation1<_A1>, class_factory_implementation2<_A1, _A2>, class_factory_implementation3<_A1, _A2, _A3> > class_factory_t; typedef typename boost::mpl::at::type type; }; // to create a specialization for a constructor parameter you should the following: // typedef class_factory_constructor_parameter::type my_constructor_parameter; #define class_factory_constructor_parameter class_factory_implementation_chooser typedef class_factory_implementation0 class_factory_default_constructor_parameter; //============================ // Implement class_factory_implementation // wrapper around class_factory_implementationN // create an instance of class _C but return a pointer to base class _B //============================ template struct class_factory_implementation { typedef _C class_type; typedef _B return_type; typedef _P parameter_type; static return_type* create_instance(parameter_type const& __params) { return __params.template create_instance(); } }; //============================ // Implement class_factory //============================ template class class_factory : private class_no_copy { public: typedef _B return_type; typedef _P parameter_type; typedef guid_t key_type; typedef return_type* (*factory_type)(parameter_type const&); private: typedef ptr_box boxed_key; typedef std::map factory_map; typedef typename factory_map::const_iterator const_iterator; typedef typename factory_map::value_type value_type; public: static bool registered(key_type __key) NO_THROW { ASSERT(__key != NULL); return __factories().find(boxed_key(__key)) != __factories().end(); } static return_type* create_instance(key_type __key, parameter_type const& __params, bool __bThrowIfError = true) { ASSERT(__key != NULL); const_iterator __i = __factories().find(boxed_key(__key)); if (__i == __factories().end()) { LOG_DEBUG(_T("no factory found for class ") << OS_SQUOTE(__key) << _T(" of type ") << OS_SQUOTE(typeid(_B).name())); if (__bThrowIfError) THROW_BAD_TYPEID_EXCEPTION(); return NULL; } return (__i->second)(__params); } static void register_factory(key_type __key, factory_type __pf) { ASSERT(__pf != NULL); ASSERT(__key != NULL); __factories().insert(value_type(boxed_key(__key), __pf)); } private: inline class_factory() NO_THROW {} inline ~class_factory() NO_THROW {} static factory_map& __factories() NO_THROW { static factory_map __g_instance; return __g_instance; } }; //============================ // Implement base_class_factory_traits //============================ template struct base_class_factory_traits : public boost::false_type { BOOST_MPL_ASSERT_NOT((boost::is_const<_C>)); // parameter_types }; #define __START_DECLARE_BASE_CLASS_FACTORY_TRAITS(_C) \ template<> \ struct base_class_factory_traits<_C> : public boost::true_type \ { \ BOOST_MPL_ASSERT_NOT((boost::is_const<_C>)); \ typedef boost::mpl::vector < \ /**/ #define CLASS_CONSTRUCTOR(_P...) ocfc::class_factory_implementation_chooser<_P>::type, #define CLASS_DEFAULT_CONSTRUCTOR CLASS_CONSTRUCTOR() #define __END_DECLARE_BASE_CLASS_FACTORY_TRAITS \ boost::mpl::na> parameter_types; \ }; \ /**/ //============================ // Implement class_factory_traits //============================ template struct class_factory_traits : public boost::false_type { BOOST_MPL_ASSERT_NOT(( boost::is_const<_C> )); // base_type }; #define __DECLARE_CLASS_FACTORY_TRAITS(_C, _B) \ template<> \ struct class_factory_traits<_C> : public boost::true_type \ { \ BOOST_MPL_ASSERT((class_guid<_C>)); \ typedef _B base_type; \ }; \ /**/ #define __CLASS_FACTORY_REG2(__nLine) __g_bClassFactoryRegistration ## __nLine #define __CLASS_FACTORY_REG(__nLine) __CLASS_FACTORY_REG2(__nLine) #define __REGISTER_CLASS_FACTORY_ALL(_C) \ namespace { \ static bool __CLASS_FACTORY_REG(__LINE__) = ocfc::detail::class_factory_registration<_C>::register_all_factories(); \ } \ /**/ #define __REGISTER_CLASS_FACTORY(_C, _P...) \ namespace { \ static bool __CLASS_FACTORY_REG(__LINE__) = ocfc::detail::class_factory_registration<_C>::register_factory< ocfc::class_factory_implementation_chooser<_P>::type >(); \ } \ /**/ #define __START_DECLARE_BASE_CLASS_FACTORY(_C) \ __DECLARE_CLASS_FACTORY_TRAITS(_C, _C) \ __START_DECLARE_BASE_CLASS_FACTORY_TRAITS(_C) \ /**/ #define __END_DECLARE_BASE_CLASS_FACTORY __END_DECLARE_BASE_CLASS_FACTORY_TRAITS // declare base class with protected constructor #define OCFC_START_DECLARE_VIRTUAL_BASE_CLASS_FACTORY __START_DECLARE_BASE_CLASS_FACTORY #define OCFC_END_DECLARE_VIRTUAL_BASE_CLASS_FACTORY __END_DECLARE_BASE_CLASS_FACTORY #define START_DECLARE_VIRTUAL_BASE_CLASS_FACTORY(_C) \ namespace ocfc { \ __START_DECLARE_BASE_CLASS_FACTORY(_C) \ /**/ #define END_DECLARE_VIRTUAL_BASE_CLASS_FACTORY \ __END_DECLARE_BASE_CLASS_FACTORY \ } \ /**/ // declare base class with public constructor #define OCFC_START_DECLARE_BASE_CLASS_FACTORY __START_DECLARE_BASE_CLASS_FACTORY #define OCFC_END_DECLARE_BASE_CLASS_FACTORY __END_DECLARE_BASE_CLASS_FACTORY #define START_DECLARE_BASE_CLASS_CONSTRUCTOR(_C) \ namespace ocfc { \ __START_DECLARE_BASE_CLASS_FACTORY(_C) \ /**/ #define END_DECLARE_BASE_CLASS_FACTORY \ __END_DECLARE_BASE_CLASS_FACTORY \ } \ /**/ #define OCFC_IMPLEMENT_BASE_CLASS_FACTORY __REGISTER_CLASS_FACTORY_ALL #define IMPLEMENT_BASE_CLASS_FACTORY __REGISTER_CLASS_FACTORY_ALL // declare class with protected constructor #define OCFC_DECLARE_VIRTUAL_CLASS_FACTORY __DECLARE_CLASS_FACTORY_TRAITS #define DECLARE_VIRTUAL_CLASS_FACTORY(_C, _B) \ namespace ocfc { \ __DECLARE_CLASS_FACTORY_TRAITS(_C, _B) \ } \ /**/ // declare class with public constructor #define OCFC_DECLARE_CLASS_FACTORY __DECLARE_CLASS_FACTORY_TRAITS #define DECLARE_CLASS_FACTORY(_C, _B) \ namespace ocfc { \ __DECLARE_CLASS_FACTORY_TRAITS(_C, _B) \ } \ /**/ #define OCFC_IMPLEMENT_CLASS_FACTORY __REGISTER_CLASS_FACTORY_ALL #define IMPLEMENT_CLASS_FACTORY __REGISTER_CLASS_FACTORY_ALL //============================ // Implement new_instance //============================ template _C* new_instance(guid_t __key, _P const& __params, bool __bThrowIfError = true) { typedef _C return_type; BOOST_MPL_ASSERT((class_factory_traits)); typedef typename class_factory_traits::base_type base_type; BOOST_MPL_ASSERT((base_class_factory_traits)); typedef typename base_class_factory_traits::parameter_types parameter_types; BOOST_MPL_ASSERT((boost::mpl::contains)); base_type* __pInstance = class_factory::create_instance(__key, __params, __bThrowIfError); if (__pInstance != NULL) { return_type* __pRet = dynamic_cast(__pInstance); if (__pRet != NULL) return __pRet; delete __pInstance; LOG_DEBUG(_T("factored class ") << OS_SQUOTE(__key) << _T(" not of type ") << OS_SQUOTE(typeid(return_type).name())); if (__bThrowIfError) THROW_BAD_TYPEID_EXCEPTION(); } return NULL; } template inline _C* new_instance(guid_t __key, bool __bThrowIfError = true) { class_factory_implementation0 __param; return new_instance<_C, class_factory_implementation0>(__key, __param, __bThrowIfError); } template inline _C* new_instance(const std::basic_string<_CharT>& __sKey, _P const& __params, bool __bThrowIfError = true) { guid_string __s = string_cast(__sKey); return new_instance<_C>(__s.c_str(), __params, __bThrowIfError); } template inline _C* new_instance(const std::basic_string<_CharT>& __sKey, bool __bThrowIfError = true) { guid_string __s = string_cast(__sKey); class_factory_implementation0 __param; return new_instance<_C>(__s.c_str(), __param, __bThrowIfError); } //============================ // Implement class_factory_registration //============================ namespace detail { template class class_factory_registration { private: BOOST_MPL_ASSERT((class_factory_traits<_C>)); typedef typename class_factory_traits<_C>::base_type base_type; BOOST_MPL_ASSERT((base_class_factory_traits)); typedef typename base_class_factory_traits::parameter_types parameter_types; BOOST_MPL_ASSERT_NOT((boost::mpl::empty)); struct for_each_end { static void register_factory() {} }; template struct for_each { typedef typename boost::mpl::pop_front<_List>::type tail_type; typedef typename boost::mpl::front<_List>::type parameter_type; typedef typename boost::mpl::if_< boost::mpl::empty, for_each_end, for_each >::type for_each_next; static void register_factory() { class_factory::register_factory(CLASS_GUID(_C), class_factory_implementation<_C, base_type, parameter_type>::create_instance); // loop for_each_next::register_factory(); } }; public: static bool register_all_factories() { for_each::register_factory(); return true; } template static bool register_factory() { BOOST_MPL_ASSERT((boost::mpl::contains)); class_factory::register_factory(CLASS_GUID(_C), class_factory_implementation<_C, base_type, _P>::create_instance); return true; } }; } // namespace detail } // namespace ocfc #endif // OCFCSENTRY_CLASS_FACTORY_HPP