From 1896d36996ab48ed7271e855d7e32b4e61f64896 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Mon, 23 Apr 2012 16:48:00 +0200 Subject: Polymorphic inheritance support --- odb/polymorphic-map.hxx | 244 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 244 insertions(+) create mode 100644 odb/polymorphic-map.hxx (limited to 'odb/polymorphic-map.hxx') diff --git a/odb/polymorphic-map.hxx b/odb/polymorphic-map.hxx new file mode 100644 index 0000000..9c18d33 --- /dev/null +++ b/odb/polymorphic-map.hxx @@ -0,0 +1,244 @@ +// file : odb/polymorphic-map.hxx +// copyright : Copyright (c) 2005-2012 Code Synthesis Tools CC +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_POLYMORPHIC_MAP_HXX +#define ODB_POLYMORPHIC_MAP_HXX + +#include + +#include +#include // std::move +#include // std::size_t +#include +#include + +#include + +#include // ODB_CXX11 +#include + +#include + +namespace odb +{ + template + struct polymorphic_map + { + typedef R root_type; + typedef polymorphic_concrete_info info_type; + typedef typename info_type::discriminator_type discriminator_type; + + polymorphic_map (): ref_count_ (1) {} + + const info_type& + find (const std::type_info& t) const; + + const info_type& + find (const discriminator_type& d) const; + + public: + typedef + std::map + type_map; + + struct discriminator_comparator + { + bool + operator() (const discriminator_type* x, + const discriminator_type* y) const + { + return *x < *y; + } + }; + + typedef + std::map + discriminator_map; + + public: + std::size_t ref_count_; + type_map type_map_; + discriminator_map discriminator_map_; + }; + + template + struct polymorphic_entry_impl + { + typedef R root_type; + typedef object_traits root_traits; + typedef polymorphic_concrete_info info_type; + + static void + insert (const info_type&); + + static void + erase (const info_type&); + }; + + template + typename object_traits::root_type>::pointer_type + create_impl () + { + typedef object_traits derived_traits; + typedef object_traits root_traits; + + typedef typename derived_traits::pointer_type derived_pointer_type; + typedef typename root_traits::pointer_type root_pointer_type; + + derived_pointer_type p ( + access::object_factory::create ()); + + // Implicit downcast. + // +#ifdef ODB_CXX11 + root_pointer_type r (std::move (p)); +#else + root_pointer_type r (p); +#endif + return r; + } + + template + struct dispatch_load + { + static void + call (database& db, T& obj, std::size_t d) + { + object_traits::load_ (db, obj, d); + } + }; + + template + struct dispatch_load + { + static void + call (database&, R&, std::size_t) + { + assert (false); + } + }; + + template + struct dispatch_persist + { + static void + call (database& db, const T& obj) + { + // Top-level call, no dynamic type checking. + // + object_traits::persist (db, obj, true, false); + } + }; + + template + struct dispatch_persist + { + static void + call (database& db, const T& obj) + { + // Top-level call, no dynamic type checking. + // + object_traits::persist (db, const_cast (obj), true, false); + } + }; + + template + bool dispatch_impl ( + typename polymorphic_concrete_info< + typename object_traits::root_type>::call_type c, + database& db, + const typename object_traits::root_type* pobj, + const void* arg) + { + typedef object_traits derived_traits; + typedef typename derived_traits::root_type root_type; + typedef object_traits root_traits; + typedef typename root_traits::id_type id_type; + typedef polymorphic_concrete_info info_type; + + bool r (false); + + switch (c) + { + case info_type::call_callback: + { + derived_traits::callback ( + db, + *const_cast (static_cast (pobj)), + *static_cast (arg)); + break; + } + case info_type::call_persist: + { + dispatch_persist::call ( + db, + *static_cast (pobj)); + break; + } + case info_type::call_update: + { + derived_traits::update ( + db, + *static_cast (pobj), + true, // Top-level call. + false); // No dynamic type checking. + break; + } + case info_type::call_find: + { + r = derived_traits::find ( + db, + *static_cast (arg), + *const_cast (static_cast (pobj)), + false); // No dynamic type checking. + break; + } + case info_type::call_reload: + { + r = derived_traits::reload ( + db, + *const_cast (static_cast (pobj)), + false); // No dynamic type checking. + break; + } + case info_type::call_load: + { + dispatch_load::call ( + db, + *const_cast (static_cast (pobj)), + *static_cast (arg)); + break; + } + case info_type::call_erase: + { + if (pobj != 0) + derived_traits::erase ( + db, + *static_cast (pobj), + true, // Top-level call. + false); // No dynamic type checking. + else + derived_traits::erase ( + db, + *static_cast (arg), + true, // Top-level call. + false); // No dynamic type checking. + break; + } + } + + return r; + } +} + +#include +#include + +#include + +#endif // ODB_POLYMORPHIC_MAP_HXX -- cgit v1.1