// file : odb/instance.hxx // copyright : Copyright (c) 2009-2015 Code Synthesis Tools CC // license : GNU GPL v3; see accompanying LICENSE file #ifndef ODB_INSTANCE_HXX #define ODB_INSTANCE_HXX #include #include #include // std::size_t #include #include #include #include #include // // Dynamic traversal instantiation support. // template struct factory { static B* create (B const& prototype) { std::string kind, name; database db (context::current ().options.database ()[0]); switch (db) { case database::common: { name = "common"; break; } case database::mssql: case database::mysql: case database::oracle: case database::pgsql: case database::sqlite: { kind = "relational"; name = kind + "::" + db.string (); break; } } if (map_ != 0) { typename map::const_iterator i; if (!name.empty ()) i = map_->find (name); if (i == map_->end ()) i = map_->find (kind); if (i != map_->end ()) return i->second (prototype); } return new B (prototype); } private: template friend struct entry; static void init () { if (factory::count_++ == 0) factory::map_ = new typename factory::map; } static void term () { if (--factory::count_ == 0) delete factory::map_; } typedef B* (*create_func) (B const&); typedef std::map map; static map* map_; static std::size_t count_; }; template typename factory::map* factory::map_; template std::size_t factory::count_; struct entry_base { static std::string name (std::type_info const&); }; template struct entry: entry_base { typedef typename D::base base; entry () { factory::init (); (*factory::map_)[name (typeid (D))] = &create; } ~entry () { factory::term (); } static base* create (base const& prototype) { return new D (prototype); } }; template struct instance { typedef typename B::base base_type; typedef ::factory factory_type; ~instance () { delete x_; } instance () { base_type prototype; x_ = factory_type::create (prototype); } template instance (A1& a1) { base_type prototype (a1); x_ = factory_type::create (prototype); } template instance (A1 const& a1) { base_type prototype (a1); x_ = factory_type::create (prototype); } template instance (A1& a1, A2& a2) { base_type prototype (a1, a2); x_ = factory_type::create (prototype); } template instance (A1 const& a1, A2 const& a2) { base_type prototype (a1, a2); x_ = factory_type::create (prototype); } template instance (A1& a1, A2& a2, A3& a3) { base_type prototype (a1, a2, a3); x_ = factory_type::create (prototype); } template instance (A1 const& a1, A2 const& a2, A3 const& a3) { base_type prototype (a1, a2, a3); x_ = factory_type::create (prototype); } template instance (A1& a1, A2& a2, A3& a3, A4& a4) { base_type prototype (a1, a2, a3, a4); x_ = factory_type::create (prototype); } template instance (A1 const& a1, A2 const& a2, A3 const& a3, A4 const& a4) { base_type prototype (a1, a2, a3, a4); x_ = factory_type::create (prototype); } template instance (A1& a1, A2& a2, A3& a3, A4& a4, A5& a5) { base_type prototype (a1, a2, a3, a4, a5); x_ = factory_type::create (prototype); } template instance (A1 const& a1, A2 const& a2, A3 const& a3, A4 const& a4, A5 const& a5) { base_type prototype (a1, a2, a3, a4, a5); x_ = factory_type::create (prototype); } template instance (A1& a1, A2& a2, A3& a3, A4& a4, A5& a5, A6 a6) { base_type prototype (a1, a2, a3, a4, a5, a6); x_ = factory_type::create (prototype); } template instance (A1 const& a1, A2 const& a2, A3 const& a3, A4 const& a4, A5 const& a5, A6 const& a6) { base_type prototype (a1, a2, a3, a4, a5, a6); x_ = factory_type::create (prototype); } instance (instance const& i) { // This is tricky: use the other instance as a prototype. // x_ = factory_type::create (*i.x_); } base_type* operator-> () const { return x_; } base_type& operator* () const { return *x_; } base_type* get () const { return x_; } private: instance& operator= (instance const&); private: base_type* x_; }; template inline traversal::edge_base& operator>> (instance& n, traversal::edge_base& e) { n->edge_traverser (e); return e; } template inline traversal::relational::edge_base& operator>> (instance& n, traversal::relational::edge_base& e) { n->edge_traverser (e); return e; } template inline traversal::node_base& operator>> (traversal::edge_base& e, instance& n) { e.node_traverser (*n); return *n; } template inline traversal::relational::node_base& operator>> (traversal::relational::edge_base& e, instance& n) { e.node_traverser (*n); return *n; } #endif // ODB_INSTANCE_HXX