diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2011-09-21 13:00:33 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2011-09-21 13:00:33 +0200 |
commit | a28444da4ca6adb016f719e032174ccb54e1692e (patch) | |
tree | 75fe8ceae2d20baa3d4b5375a832598efe8b2fce | |
parent | 0046a34d5ad5fc1e88b33279605f179646b0ea59 (diff) |
Rework const object handling
Now objects are always loaded as non-const and the object cache in
session treats all objects as non-const.
-rw-r--r-- | odb/cache-traits.hxx | 20 | ||||
-rw-r--r-- | odb/database.hxx | 6 | ||||
-rw-r--r-- | odb/database.ixx | 36 | ||||
-rw-r--r-- | odb/database.txx | 57 | ||||
-rw-r--r-- | odb/exceptions.cxx | 6 | ||||
-rw-r--r-- | odb/exceptions.hxx | 7 | ||||
-rw-r--r-- | odb/object-result.hxx | 59 | ||||
-rw-r--r-- | odb/object-result.txx | 21 | ||||
-rw-r--r-- | odb/pointer-traits.hxx | 15 | ||||
-rw-r--r-- | odb/session.hxx | 30 | ||||
-rw-r--r-- | odb/session.ixx | 47 | ||||
-rw-r--r-- | odb/session.txx | 49 | ||||
-rw-r--r-- | odb/tr1/pointer-traits.hxx | 11 | ||||
-rw-r--r-- | odb/traits.hxx | 20 | ||||
-rw-r--r-- | odb/view-result.hxx | 57 | ||||
-rw-r--r-- | odb/view-result.txx | 2 |
16 files changed, 216 insertions, 227 deletions
diff --git a/odb/cache-traits.hxx b/odb/cache-traits.hxx index 596ee35..e4b2495 100644 --- a/odb/cache-traits.hxx +++ b/odb/cache-traits.hxx @@ -21,9 +21,14 @@ namespace odb struct pointer_cache_traits { typedef P pointer_type; - typedef typename pointer_traits<pointer_type>::element_type element_type; + typedef odb::pointer_traits<pointer_type> pointer_traits; + typedef typename pointer_traits::element_type element_type; + + // element_type can be const while object_type is always non-const. + // + typedef typename object_traits<element_type>::object_type object_type; typedef typename object_traits<element_type>::id_type id_type; - typedef session::object_position<element_type> position_type; + typedef session::object_position<object_type> position_type; struct insert_guard { @@ -46,7 +51,10 @@ namespace odb insert (odb::database& db, const id_type& id, const pointer_type& p) { if (session::has_current ()) - return session::current ().insert<element_type> (db, id, p); + // Cast away constness if any. + // + return session::current ().insert<object_type> ( + db, id, pointer_traits::cast (p)); else return position_type (); } @@ -55,7 +63,7 @@ namespace odb find (odb::database& db, const id_type& id) { if (session::has_current ()) - return session::current ().find<element_type> (db, id); + return session::current ().find<object_type> (db, id); else return pointer_type (); } @@ -64,14 +72,14 @@ namespace odb erase (odb::database& db, const id_type& id) { if (session::has_current ()) - session::current ().erase<element_type> (db, id); + session::current ().erase<object_type> (db, id); } static void erase (const position_type& p) { if (p.map_ != 0) - session::current ().erase<element_type> (p); + session::current ().erase<object_type> (p); } }; diff --git a/odb/database.hxx b/odb/database.hxx index f24e0fa..7e29ddf 100644 --- a/odb/database.hxx +++ b/odb/database.hxx @@ -19,7 +19,6 @@ #include <odb/exceptions.hxx> #include <odb/details/export.hxx> -#include <odb/details/meta/remove-const.hxx> namespace odb { @@ -142,7 +141,7 @@ namespace odb template <typename T> unsigned long long - erase_query (const odb::query<typename object_traits<T>::object_type>&); + erase_query (const odb::query<T>&); // Query API. // @@ -160,8 +159,7 @@ namespace odb template <typename T> result<T> - query (const odb::query<typename details::meta::remove_const<T>::result>&, - bool cache = true); + query (const odb::query<T>&, bool cache = true); // Native database statement execution. // diff --git a/odb/database.ixx b/odb/database.ixx index c4b3c77..7bc6520 100644 --- a/odb/database.ixx +++ b/odb/database.ixx @@ -167,66 +167,48 @@ namespace odb inline unsigned long long database:: erase_query () { - // T can be const T while object_type will always be T. + // T is always object_type. // - typedef typename odb::object_traits<T>::object_type object_type; - - return erase_query<T> (odb::query<object_type> ()); + return erase_query<T> (odb::query<T> ()); } template <typename T> inline unsigned long long database:: erase_query (const char* q) { - // T can be const T while object_type will always be T. + // T is always object_type. // - typedef typename odb::object_traits<T>::object_type object_type; - - return erase_query<T> (odb::query<object_type> (q)); + return erase_query<T> (odb::query<T> (q)); } template <typename T> inline unsigned long long database:: erase_query (const std::string& q) { - // T can be const T while object_type will always be T. + // T is always object_type. // - typedef typename odb::object_traits<T>::object_type object_type; - - return erase_query<T> (odb::query<object_type> (q)); + return erase_query<T> (odb::query<T> (q)); } template <typename T> inline result<T> database:: query (bool cache) { - // T can be const T. - // - typedef typename details::meta::remove_const<T>::result type; - - return query<T> (odb::query<type> (), cache); + return query<T> (odb::query<T> (), cache); } template <typename T> inline result<T> database:: query (const char* q, bool cache) { - // T can be const T. - // - typedef typename details::meta::remove_const<T>::result type; - - return query<T> (odb::query<type> (q), cache); + return query<T> (odb::query<T> (q), cache); } template <typename T> inline result<T> database:: query (const std::string& q, bool cache) { - // T can be const T. - // - typedef typename details::meta::remove_const<T>::result type; - - return query<T> (odb::query<type> (q), cache); + return query<T> (odb::query<T> (q), cache); } inline unsigned long long database:: diff --git a/odb/database.txx b/odb/database.txx index 8117997..82afd64 100644 --- a/odb/database.txx +++ b/odb/database.txx @@ -63,6 +63,8 @@ namespace odb typename object_traits<T>::pointer_type database:: load (const typename object_traits<T>::id_type& id) { + // T is always object_type. + // typedef typename object_traits<T>::pointer_type pointer_type; typedef odb::pointer_traits<pointer_type> pointer_traits; @@ -86,12 +88,10 @@ namespace odb typename object_traits<T>::pointer_type database:: find (const typename object_traits<T>::id_type& id) { - // T can be const T while object_type will always be T. + // T is always object_type. // - typedef typename odb::object_traits<T>::object_type object_type; - typedef odb::object_traits<object_type> object_traits; - - typedef typename odb::object_traits<T>::pointer_type pointer_type; + typedef odb::object_traits<T> object_traits; + typedef typename object_traits::pointer_type pointer_type; typedef odb::pointer_traits<pointer_type> pointer_traits; // First check the session. @@ -117,15 +117,12 @@ namespace odb bool database:: find (const typename object_traits<T>::id_type& id, T& obj) { - // T can be const T while object_type will always be T. + // T is always object_type. // - typedef typename odb::object_traits<T>::object_type object_type; - typedef odb::object_traits<object_type> object_traits; - if (!transaction::has_current ()) throw not_in_transaction (); - return object_traits::find (*this, id, obj); + return object_traits<T>::find (*this, id, obj); } template <typename T> @@ -171,12 +168,10 @@ namespace odb void database:: erase (const typename object_traits<T>::id_type& id) { - // T can be const T while object_type will always be T. + // T is always object_type. // - typedef typename odb::object_traits<T>::object_type object_type; - typedef odb::object_traits<object_type> object_traits; - - typedef typename odb::object_traits<T>::pointer_type pointer_type; + typedef odb::object_traits<T> object_traits; + typedef typename object_traits::pointer_type pointer_type; if (!transaction::has_current ()) throw not_in_transaction (); @@ -193,8 +188,7 @@ namespace odb // typedef typename odb::object_traits<T>::object_type object_type; typedef odb::object_traits<object_type> object_traits; - - typedef typename odb::object_traits<T>::pointer_type pointer_type; + typedef typename object_traits::pointer_type pointer_type; if (!transaction::has_current ()) throw not_in_transaction (); @@ -209,53 +203,42 @@ namespace odb template <typename T> unsigned long long database:: - erase_query (const odb::query<typename object_traits<T>::object_type>& q) + erase_query (const odb::query<T>& q) { - // T can be const T while object_type will always be T. + // T is always object_type. // - typedef typename odb::object_traits<T>::object_type object_type; - typedef odb::object_traits<object_type> object_traits; - if (!transaction::has_current ()) throw not_in_transaction (); - return object_traits::erase_query (*this, q); + return object_traits<T>::erase_query (*this, q); } template <typename T> struct database::query_<T, class_object> { - // T can be const T while object_type will always be T. - // - typedef typename odb::object_traits<T>::object_type object_type; - typedef odb::object_traits<object_type> object_traits; - static result<T> - call (database& db, const odb::query<object_type>& q) + call (database& db, const odb::query<T>& q) { - return object_traits::template query<T> (db, q); + return object_traits<T>::query (db, q); } }; template <typename T> struct database::query_<T, class_view> { - // Const views are not supported. - // - typedef odb::view_traits<T> view_traits; - static result<T> call (database& db, const odb::query<T>& q) { - return view_traits::query (db, q); + return view_traits<T>::query (db, q); } }; template <typename T> result<T> database:: - query (const odb::query<typename details::meta::remove_const<T>::result>& q, - bool cache) + query (const odb::query<T>& q, bool cache) { + // T is always object_type. + // if (!transaction::has_current ()) throw not_in_transaction (); diff --git a/odb/exceptions.cxx b/odb/exceptions.cxx index b79f189..bc4b509 100644 --- a/odb/exceptions.cxx +++ b/odb/exceptions.cxx @@ -47,12 +47,6 @@ namespace odb return "session not in effect in this thread"; } - const char* const_object:: - what () const throw () - { - return "object cached in session is const"; - } - const char* deadlock:: what () const throw () { diff --git a/odb/exceptions.hxx b/odb/exceptions.hxx index b1e4711..698baee 100644 --- a/odb/exceptions.hxx +++ b/odb/exceptions.hxx @@ -56,12 +56,6 @@ namespace odb what () const throw (); }; - struct LIBODB_EXPORT const_object: exception - { - virtual const char* - what () const throw (); - }; - // Database operations exceptions. // struct LIBODB_EXPORT recoverable: exception @@ -139,7 +133,6 @@ namespace odb using odb::already_in_session; using odb::not_in_session; - using odb::const_object; using odb::recoverable; using odb::deadlock; diff --git a/odb/object-result.hxx b/odb/object-result.hxx index fcee125..235b682 100644 --- a/odb/object-result.hxx +++ b/odb/object-result.hxx @@ -28,16 +28,20 @@ namespace odb protected: friend class result<T, class_object>; + friend class result<const T, class_object>; friend class result_iterator<T, class_object>; + friend class result_iterator<const T, class_object>; typedef odb::database database_type; - typedef typename odb::object_traits<T>::pointer_type pointer_type; - typedef odb::pointer_traits<pointer_type> pointer_traits; - - typedef typename odb::object_traits<T>::object_type object_type; - typedef typename odb::object_traits<T>::id_type id_type; + // In result_impl, T is always non-const and the same as object_type. + // + typedef T object_type; typedef odb::object_traits<object_type> object_traits; + typedef typename object_traits::id_type id_type; + + typedef typename object_traits::pointer_type pointer_type; + typedef odb::pointer_traits<pointer_type> pointer_traits; result_impl (database_type& db) : begin_ (true), end_ (false), db_ (db), current_ () @@ -123,12 +127,12 @@ namespace odb typedef std::ptrdiff_t difference_type; typedef std::input_iterator_tag iterator_category; - // T might be const T, but object_type is always T. + // T can be const T while object_type is always non-const. // typedef typename object_traits<T>::object_type object_type; typedef typename object_traits<T>::id_type id_type; - typedef result_impl<T, class_object> result_impl_type; + typedef result_impl<object_type, class_object> result_impl_type; public: explicit @@ -192,8 +196,11 @@ namespace odb } private: + // Use unrestricted pointer traits since that's what is returned by + // result_impl. + // typedef - odb::pointer_traits<typename object_traits<T>::pointer_type> + odb::pointer_traits<typename object_traits<object_type>::pointer_type> pointer_traits; result_impl_type* res_; @@ -234,7 +241,10 @@ namespace odb typedef std::size_t size_type; typedef std::ptrdiff_t difference_type; - typedef result_impl<T, class_object> result_impl_type; + // T can be const T while object_type is always non-const. + // + typedef typename object_traits<T>::object_type object_type; + typedef result_impl<object_type, class_object> result_impl_type; public: result () @@ -267,6 +277,35 @@ namespace odb return *this; } + // Conversion from result<T> to result<const T>. + // + template <typename UT> + result (const result<UT, class_object>& r) + // + // If you get a compiler error pointing to the line below saying + // that the impl_ member is inaccessible, then you are most likely + // trying to perform an illegal result conversion, for example, + // from result<const obj> to result<obj>. + // + : impl_ (r.impl_) + { + } + + template <typename UT> + result& + operator= (const result<UT, class_object>& r) + { + // If you get a compiler error pointing to the line below saying + // that the impl_ member is inaccessible, then you are most likely + // trying to perform an illegal result conversion, for example, + // from result<const obj> to result<obj>. + // + if (impl_ != r.impl_) + impl_ = r.impl_; + + return *this; + } + void swap (result& r) { @@ -325,6 +364,8 @@ namespace odb } private: + friend class result<const T, class_object>; + details::shared_ptr<result_impl_type> impl_; }; } diff --git a/odb/object-result.txx b/odb/object-result.txx index bd4e95e..c19e482 100644 --- a/odb/object-result.txx +++ b/odb/object-result.txx @@ -23,16 +23,13 @@ namespace odb result_impl<T, class_object>:: current () { - typedef typename object_traits::pointer_type unrestricted_pointer_type; - typedef typename object_traits::pointer_traits unrestricted_pointer_traits; - if (pointer_traits::null_ptr (current_) && !end_) { if (!session::has_current ()) { - unrestricted_pointer_type up (object_traits::create ()); - object_type& obj (unrestricted_pointer_traits::get_ref (up)); - current (pointer_type (up)); + pointer_type p (object_traits::create ()); + object_type& obj (pointer_traits::get_ref (p)); + current (p); load (obj); } else @@ -48,15 +45,13 @@ namespace odb current (p); else { - unrestricted_pointer_type up (object_traits::create ()); + pointer_type p (object_traits::create ()); - typename - pointer_cache_traits<unrestricted_pointer_type>::insert_guard ig ( - pointer_cache_traits<unrestricted_pointer_type>::insert ( - database (), id, up)); + typename pointer_cache_traits<pointer_type>::insert_guard ig ( + pointer_cache_traits<pointer_type>::insert (database (), id, p)); - object_type& obj (unrestricted_pointer_traits::get_ref (up)); - current (pointer_type (up)); + object_type& obj (pointer_traits::get_ref (p)); + current (p); load (obj); ig.release (); } diff --git a/odb/pointer-traits.hxx b/odb/pointer-traits.hxx index 8882309..f8eed3a 100644 --- a/odb/pointer-traits.hxx +++ b/odb/pointer-traits.hxx @@ -12,6 +12,8 @@ #include <memory> // std::auto_ptr #include <cstddef> // std::size_t +#include <odb/details/meta/remove-const.hxx> + namespace odb { enum pointer_kind @@ -81,6 +83,8 @@ namespace odb typedef T element_type; typedef T* pointer_type; typedef const T* const_pointer_type; + typedef typename details::meta::remove_const<T>::result* + unrestricted_pointer_type; typedef raw_ptr_guard<pointer_type> guard; // Return raw pointer to the pointed-to element, including NULL. @@ -107,6 +111,14 @@ namespace odb return p == 0; } + // Cast away constness. + // + static unrestricted_pointer_type + cast (pointer_type p) + { + return const_cast<unrestricted_pointer_type> (p); + } + public: // Allocate memory for an element that will be managed by this // pointer. @@ -162,6 +174,9 @@ namespace odb return p.get () == 0; } + // cast() is not provided since it transfers the ownership. + // + public: static void* allocate (std::size_t n) diff --git a/odb/session.hxx b/odb/session.hxx index d1b61a2..65d0987 100644 --- a/odb/session.hxx +++ b/odb/session.hxx @@ -67,31 +67,6 @@ namespace odb session& operator= (const session&); protected: - template <typename T> - struct object_pointers - { - typedef typename object_traits<T>::pointer_type pointer_type; - typedef typename object_traits<T>::const_pointer_type const_pointer_type; - - object_pointers (); - - void - set (const pointer_type&); - - void - set (const const_pointer_type&); - - void - get (pointer_type& p) const; - - void - get (const_pointer_type& cp) const; - - private: - pointer_type p_; - const_pointer_type cp_; - }; - struct LIBODB_EXPORT object_map_base: details::shared_base { virtual @@ -101,7 +76,8 @@ namespace odb template <typename T> struct object_map: object_map_base, - std::map< typename object_traits<T>::id_type, object_pointers<T> > + std::map<typename object_traits<T>::id_type, + typename object_traits<T>::pointer_type> { }; @@ -111,7 +87,7 @@ namespace odb template <typename T> struct object_position { - typedef typename object_traits<T>::object_type object_type; + typedef T object_type; typedef object_map<object_type> map; typedef typename map::iterator iterator; diff --git a/odb/session.ixx b/odb/session.ixx index c6708b7..573deb2 100644 --- a/odb/session.ixx +++ b/odb/session.ixx @@ -15,51 +15,4 @@ namespace odb // p.map_->erase (p.pos_); } - - // - // object_pointers - // - template <typename T> - inline session::object_pointers<T>:: - object_pointers () : p_ (), cp_ () {} - - template <typename T> - inline void session::object_pointers<T>:: - set (const pointer_type& p) - { - p_ = p; - cp_ = const_pointer_type (); - } - - template <typename T> - inline void session::object_pointers<T>:: - set (const const_pointer_type& cp) - { - p_ = pointer_type (); - cp_ = cp; - } - - template <typename T> - inline void session::object_pointers<T>:: - get (pointer_type& p) const - { - if (!pointer_traits<pointer_type>::null_ptr (p_)) - p = p_; - else if (!pointer_traits<const_pointer_type>::null_ptr (cp_)) - throw const_object (); - else - p = pointer_type (); - } - - template <typename T> - inline void session::object_pointers<T>:: - get (const_pointer_type& cp) const - { - if (!pointer_traits<pointer_type>::null_ptr (p_)) - cp = const_pointer_type (p_); - else if (!pointer_traits<const_pointer_type>::null_ptr (cp_)) - cp = cp_; - else - cp = const_pointer_type (); - } } diff --git a/odb/session.txx b/odb/session.txx index e2d7734..31814f8 100644 --- a/odb/session.txx +++ b/odb/session.txx @@ -13,28 +13,20 @@ namespace odb const typename object_traits<T>::id_type& id, const typename object_traits<T>::pointer_type& obj) { - // T can be const T while object_type will always be T. - // - typedef typename object_traits<T>::object_type object_type; - typedef odb::object_traits<object_type> object_traits; - - typedef typename odb::object_traits<T>::pointer_type pointer_type; + typedef odb::object_traits<T> object_traits; + typedef typename object_traits::pointer_type pointer_type; typedef odb::pointer_traits<pointer_type> pointer_traits; type_map& tm (db_map_[&db]); - details::shared_ptr<object_map_base>& pom (tm[&typeid (object_type)]); + details::shared_ptr<object_map_base>& pom (tm[&typeid (T)]); if (!pom) - pom.reset (new (details::shared) object_map<object_type>); + pom.reset (new (details::shared) object_map<T>); - object_map<object_type>& om ( - static_cast<object_map<object_type>&> (*pom)); + object_map<T>& om (static_cast<object_map<T>&> (*pom)); - typename object_map<object_type>::value_type vt ( - id, object_pointers<object_type> ()); - vt.second.set (obj); - std::pair<typename object_map<object_type>::iterator, bool> r ( - om.insert (vt)); + typename object_map<T>::value_type vt (id, obj); + std::pair<typename object_map<T>::iterator, bool> r (om.insert (vt)); // In what situation may we possibly attempt to reinsert the object? // For example, when the user loads the same object in to different @@ -42,7 +34,7 @@ namespace odb // we should probably update our entries accordingly. // if (!r.second) - r.first->second.set (obj); + r.first->second = obj; return object_position<T> (om, r.first); } @@ -51,9 +43,6 @@ namespace odb typename object_traits<T>::pointer_type session:: find (database_type& db, const typename object_traits<T>::id_type& id) const { - // T can be const T while object_type will always be T. - // - typedef typename object_traits<T>::object_type object_type; typedef typename object_traits<T>::pointer_type pointer_type; database_map::const_iterator di (db_map_.find (&db)); @@ -62,45 +51,37 @@ namespace odb return pointer_type (); const type_map& tm (di->second); - type_map::const_iterator ti (tm.find (&typeid (object_type))); + type_map::const_iterator ti (tm.find (&typeid (T))); if (ti == tm.end ()) return pointer_type (); - const object_map<object_type>& om ( - static_cast<const object_map<object_type>&> (*ti->second)); - typename object_map<object_type>::const_iterator oi (om.find (id)); + const object_map<T>& om (static_cast<const object_map<T>&> (*ti->second)); + typename object_map<T>::const_iterator oi (om.find (id)); if (oi == om.end ()) return pointer_type (); - pointer_type r; - oi->second.get (r); - return r; + return oi->second; } template <typename T> void session:: erase (database_type& db, const typename object_traits<T>::id_type& id) { - // T can be const T while object_type will always be T. - // - typedef typename object_traits<T>::object_type object_type; - database_map::iterator di (db_map_.find (&db)); if (di == db_map_.end ()) return; type_map& tm (di->second); - type_map::iterator ti (tm.find (&typeid (object_type))); + type_map::iterator ti (tm.find (&typeid (T))); if (ti == tm.end ()) return; - object_map<object_type>& om ( - static_cast<object_map<object_type>&> (*ti->second)); - typename object_map<object_type>::iterator oi (om.find (id)); + object_map<T>& om (static_cast<object_map<T>&> (*ti->second)); + typename object_map<T>::iterator oi (om.find (id)); if (oi == om.end ()) return; diff --git a/odb/tr1/pointer-traits.hxx b/odb/tr1/pointer-traits.hxx index 80f6419..b6ef5ae 100644 --- a/odb/tr1/pointer-traits.hxx +++ b/odb/tr1/pointer-traits.hxx @@ -14,6 +14,7 @@ // #include <odb/pointer-traits.hxx> +#include <odb/details/meta/remove-const.hxx> namespace odb { @@ -29,6 +30,10 @@ namespace odb typedef T element_type; typedef std::tr1::shared_ptr<element_type> pointer_type; typedef std::tr1::shared_ptr<const element_type> const_pointer_type; + typedef typename details::meta::remove_const<element_type>::result + unrestricted_element_type; + typedef std::tr1::shared_ptr<unrestricted_element_type> + unrestricted_pointer_type; typedef smart_ptr_guard<pointer_type> guard; static element_type* @@ -49,6 +54,12 @@ namespace odb return !p; } + static unrestricted_pointer_type + cast (const pointer_type& p) + { + return std::tr1::const_pointer_cast<unrestricted_element_type> (p); + } + public: static void* allocate (std::size_t n) diff --git a/odb/traits.hxx b/odb/traits.hxx index 3f400cb..4d136af 100644 --- a/odb/traits.hxx +++ b/odb/traits.hxx @@ -194,6 +194,26 @@ namespace odb typedef typename access::view_traits<T>::pointer_type pointer_type; }; + // Specialization for const views. It only defines the view, pointer, + // and const_pointer types with pointer and const_pointer being the + // same. Similar to objects, the idea is to only use this specialization + // in the interfaces, with the implementations detecting this situation + // and using the non-const view_traits version. + // + template <typename T> + struct view_traits<const T> + { + private: + typedef + odb::pointer_traits<typename access::view_traits<T>::pointer_type> + pointer_traits; + + public: + typedef typename access::view_traits<T>::view_type view_type; + typedef typename pointer_traits::const_pointer_type const_pointer_type; + typedef const_pointer_type pointer_type; + }; + // // composite_value_traits // diff --git a/odb/view-result.hxx b/odb/view-result.hxx index 088969a..ef9ffd8 100644 --- a/odb/view-result.hxx +++ b/odb/view-result.hxx @@ -28,16 +28,20 @@ namespace odb protected: friend class result<T, class_view>; + friend class result<const T, class_view>; friend class result_iterator<T, class_view>; + friend class result_iterator<const T, class_view>; typedef odb::database database_type; - typedef typename odb::view_traits<T>::pointer_type pointer_type; - typedef odb::pointer_traits<pointer_type> pointer_traits; - - typedef typename odb::view_traits<T>::view_type view_type; + // In result_impl, T is always non-const and the same as view_type. + // + typedef T view_type; typedef odb::view_traits<view_type> view_traits; + typedef typename view_traits::pointer_type pointer_type; + typedef odb::pointer_traits<pointer_type> pointer_traits; + result_impl (database_type& db) : begin_ (true), end_ (false), db_ (db), current_ () { @@ -119,11 +123,11 @@ namespace odb typedef std::ptrdiff_t difference_type; typedef std::input_iterator_tag iterator_category; - // Const views are not supported, so this should be the same as T. + // T can be const T while view_type is always non-const. // typedef typename view_traits<T>::view_type view_type; - typedef result_impl<T, class_view> result_impl_type; + typedef result_impl<view_type, class_view> result_impl_type; public: explicit @@ -187,8 +191,11 @@ namespace odb } private: + // Use unrestricted pointer traits since that's what is returned by + // result_impl. + // typedef - odb::pointer_traits<typename view_traits<T>::pointer_type> + odb::pointer_traits<typename view_traits<view_type>::pointer_type> pointer_traits; result_impl_type* res_; @@ -229,7 +236,10 @@ namespace odb typedef std::size_t size_type; typedef std::ptrdiff_t difference_type; - typedef result_impl<T, class_view> result_impl_type; + // T can be const T while view_type is always non-const. + // + typedef typename view_traits<T>::view_type view_type; + typedef result_impl<view_type, class_view> result_impl_type; public: result () @@ -262,6 +272,35 @@ namespace odb return *this; } + // Conversion from result<T> to result<const T>. + // + template <typename UT> + result (const result<UT, class_view>& r) + // + // If you get a compiler error pointing to the line below saying + // that the impl_ member is inaccessible, then you are most likely + // trying to perform an illegal result conversion, for example, + // from result<const obj> to result<obj>. + // + : impl_ (r.impl_) + { + } + + template <typename UT> + result& + operator= (const result<UT, class_view>& r) + { + // If you get a compiler error pointing to the line below saying + // that the impl_ member is inaccessible, then you are most likely + // trying to perform an illegal result conversion, for example, + // from result<const obj> to result<obj>. + // + if (impl_ != r.impl_) + impl_ = r.impl_; + + return *this; + } + void swap (result& r) { @@ -320,6 +359,8 @@ namespace odb } private: + friend class result<const T, class_view>; + details::shared_ptr<result_impl_type> impl_; }; } diff --git a/odb/view-result.txx b/odb/view-result.txx index 52d478e..95f34e0 100644 --- a/odb/view-result.txx +++ b/odb/view-result.txx @@ -22,8 +22,6 @@ namespace odb { if (pointer_traits::null_ptr (current_) && !end_) { - // For views, pointer_type is unrestricted_pointer_type. - // pointer_type p (view_traits::create ()); view_type& view (pointer_traits::get_ref (p)); current (p); |