aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2011-09-21 13:00:33 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2011-09-21 13:00:33 +0200
commita28444da4ca6adb016f719e032174ccb54e1692e (patch)
tree75fe8ceae2d20baa3d4b5375a832598efe8b2fce
parent0046a34d5ad5fc1e88b33279605f179646b0ea59 (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.hxx20
-rw-r--r--odb/database.hxx6
-rw-r--r--odb/database.ixx36
-rw-r--r--odb/database.txx57
-rw-r--r--odb/exceptions.cxx6
-rw-r--r--odb/exceptions.hxx7
-rw-r--r--odb/object-result.hxx59
-rw-r--r--odb/object-result.txx21
-rw-r--r--odb/pointer-traits.hxx15
-rw-r--r--odb/session.hxx30
-rw-r--r--odb/session.ixx47
-rw-r--r--odb/session.txx49
-rw-r--r--odb/tr1/pointer-traits.hxx11
-rw-r--r--odb/traits.hxx20
-rw-r--r--odb/view-result.hxx57
-rw-r--r--odb/view-result.txx2
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);