summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2024-04-22 13:33:29 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2024-04-22 13:33:29 +0200
commit3795f78c8d5fccddf648b80c10c0d1a244ddb085 (patch)
tree15708edccb9421b3d8f4000e891d5865b6696265
parentacbfbc951eebd17d9d59066f32ba0875cd2c6747 (diff)
Improve odb::nullable for C++11 and later
-rw-r--r--libodb/odb/nullable.hxx335
1 files changed, 299 insertions, 36 deletions
diff --git a/libodb/odb/nullable.hxx b/libodb/odb/nullable.hxx
index d13f0c9..75f5892 100644
--- a/libodb/odb/nullable.hxx
+++ b/libodb/odb/nullable.hxx
@@ -6,6 +6,12 @@
#include <odb/pre.hxx>
+#include <odb/details/config.hxx> // ODB_CXX11
+
+#ifdef ODB_CXX11
+# include <utility> // std::move
+#endif
+
#include <odb/forward.hxx> // odb::core
namespace odb
@@ -25,6 +31,18 @@ namespace odb
nullable& operator= (const nullable&);
template <typename Y> nullable& operator= (const nullable<Y>&);
+#ifdef ODB_CXX11
+ nullable (T&&);
+ nullable (nullable&&);
+ template <typename Y> explicit nullable (nullable<Y>&&);
+
+ nullable& operator= (T&&);
+ nullable& operator= (nullable&&);
+ template <typename Y> nullable& operator= (nullable<Y>&&);
+
+ ~nullable ();
+#endif
+
void swap (nullable&);
bool null () const;
@@ -49,7 +67,18 @@ namespace odb
private:
void true_value () {};
+#ifdef ODB_CXX11
+ struct empty {};
+
+ union
+ {
+ empty empty_;
+ T value_;
+ };
+#else
T value_;
+#endif
+
bool null_;
};
@@ -92,6 +121,55 @@ namespace odb
operator>= (const nullable<T>& x, const nullable<T>& y) {return !(x < y);}
template <typename T>
+ inline bool nullable<T>::
+ null () const
+ {
+ return null_;
+ }
+
+ template <typename T>
+ inline T& nullable<T>::
+ get ()
+ {
+ return value_;
+ }
+
+ template <typename T>
+ inline const T& nullable<T>::
+ get () const
+ {
+ return value_;
+ }
+
+ template <typename T>
+ inline T* nullable<T>::
+ operator-> ()
+ {
+ return null_ ? 0 : &value_;
+ }
+
+ template <typename T>
+ inline const T* nullable<T>::
+ operator-> () const
+ {
+ return null_ ? 0 : &value_;
+ }
+
+ template <typename T>
+ inline T& nullable<T>::
+ operator* ()
+ {
+ return value_;
+ }
+
+ template <typename T>
+ inline const T& nullable<T>::
+ operator* () const
+ {
+ return value_;
+ }
+
+ template <typename T>
inline nullable<T>::
nullable ()
: null_ (true)
@@ -105,27 +183,80 @@ namespace odb
{
}
+#ifdef ODB_CXX11
+
+ template <typename T>
+ inline nullable<T>::
+ nullable (T&& v)
+ : value_ (std::move (v)), null_ (false)
+ {
+ }
+
template <typename T>
inline nullable<T>::
nullable (const nullable& y)
- : value_ (y.value_), null_ (y.null_)
+ : null_ (y.null_)
+ {
+ if (!null_)
+ new (&value_) T (y.value_);
+ }
+
+ template <typename T>
+ inline nullable<T>::
+ nullable (nullable&& y)
+ : null_ (y.null_)
{
+ if (!null_)
+ new (&value_) T (std::move (y.value_));
}
template <typename T>
template <typename Y>
inline nullable<T>::
nullable (const nullable<Y>& y)
- : value_ (y.value_), null_ (y.null_)
+ : null_ (y.null_)
+ {
+ if (!null_)
+ new (&value_) T (y.value_);
+ }
+
+ template <typename T>
+ template <typename Y>
+ inline nullable<T>::
+ nullable (nullable<Y>&& y)
+ : null_ (y.null_)
{
+ if (!null_)
+ new (&value_) T (std::move (y.value_));
}
template <typename T>
inline nullable<T>& nullable<T>::
operator= (const T& v)
{
- value_ = v;
- null_ = false;
+ if (!null_)
+ value_ = v;
+ else
+ {
+ new (&value_) T (v);
+ null_ = false;
+ }
+
+ return *this;
+ }
+
+ template <typename T>
+ inline nullable<T>& nullable<T>::
+ operator= (T&& v)
+ {
+ if (!null_)
+ value_ = std::move (v);
+ else
+ {
+ new (&value_) T (std::move (v));
+ null_ = false;
+ }
+
return *this;
}
@@ -135,8 +266,47 @@ namespace odb
{
if (this != &y)
{
- value_ = y.value_;
- null_ = y.null_;
+ if (!y.null_)
+ {
+ if (!null_)
+ value_ = y.value_;
+ else
+ {
+ new (&value_) T (y.value_);
+ null_ = false;
+ }
+ }
+ else if (!null_)
+ {
+ value_.~T ();
+ null_ = true;
+ }
+ }
+
+ return *this;
+ }
+
+ template <typename T>
+ inline nullable<T>& nullable<T>::
+ operator= (nullable&& y)
+ {
+ if (this != &y)
+ {
+ if (!y.null_)
+ {
+ if (!null_)
+ value_ = std::move (y.value_);
+ else
+ {
+ new (&value_) T (std::move (y.value_));
+ null_ = false;
+ }
+ }
+ else if (!null_)
+ {
+ value_.~T ();
+ null_ = true;
+ }
}
return *this;
@@ -147,8 +317,46 @@ namespace odb
inline nullable<T>& nullable<T>::
operator= (const nullable<Y>& y)
{
- value_ = y.value_;
- null_ = y.null_;
+ if (!y.null_)
+ {
+ if (!null_)
+ value_ = y.value_;
+ else
+ {
+ new (&value_) T (y.value_);
+ null_ = false;
+ }
+ }
+ else if (!null_)
+ {
+ value_.~T ();
+ null_ = true;
+ }
+
+ return *this;
+ }
+
+ template <typename T>
+ template <typename Y>
+ inline nullable<T>& nullable<T>::
+ operator= (nullable<Y>&& y)
+ {
+ if (!y.null_)
+ {
+ if (!null_)
+ value_ = std::move (y.value_);
+ else
+ {
+ new (&value_) T (std::move (y.value_));
+ null_ = false;
+ }
+ }
+ else if (!null_)
+ {
+ value_.~T ();
+ null_ = true;
+ }
+
return *this;
}
@@ -156,63 +364,116 @@ namespace odb
inline void nullable<T>::
swap (nullable& y)
{
- T v (value_);
- bool n (null_);
-
- value_ = y.value_;
- null_ = y.null_;
+ if (!y.null_)
+ {
+ if (!null_)
+ {
+ T v (std::move (value_));
+ value_ = y.value_;
+ y.value_ = v;
+ }
+ else
+ {
+ new (&value_) T (std::move (y.value_));
+ null_ = false;
+
+ y.value_.~T ();
+ y.null_ = true;
+ }
+ }
+ else
+ {
+ if (!null_)
+ {
+ new (&y.value_) T (std::move (value_));
+ y.null_ = false;
+
+ value_.~T ();
+ null_ = true;
+ }
+ }
+ }
- y.value_ = v;
- y.null_ = n;
+ template <typename T>
+ inline void nullable<T>::
+ reset ()
+ {
+ if (!null_)
+ {
+ value_.~T ();
+ null_ = true;
+ }
}
template <typename T>
- inline bool nullable<T>::
- null () const
+ inline nullable<T>::
+ ~nullable ()
{
- return null_;
+ if (!null_)
+ value_.~T ();
}
+#else // C++98
+
template <typename T>
- inline T& nullable<T>::
- get ()
+ inline nullable<T>::
+ nullable (const nullable& y)
+ : value_ (y.value_), null_ (y.null_)
{
- return value_;
}
template <typename T>
- inline const T& nullable<T>::
- get () const
+ template <typename Y>
+ inline nullable<T>::
+ nullable (const nullable<Y>& y)
+ : value_ (y.value_), null_ (y.null_)
{
- return value_;
}
template <typename T>
- inline T* nullable<T>::
- operator-> ()
+ inline nullable<T>& nullable<T>::
+ operator= (const T& v)
{
- return null_ ? 0 : &value_;
+ value_ = v;
+ null_ = false;
+ return *this;
}
template <typename T>
- inline const T* nullable<T>::
- operator-> () const
+ inline nullable<T>& nullable<T>::
+ operator= (const nullable& y)
{
- return null_ ? 0 : &value_;
+ if (this != &y)
+ {
+ value_ = y.value_;
+ null_ = y.null_;
+ }
+
+ return *this;
}
template <typename T>
- inline T& nullable<T>::
- operator* ()
+ template <typename Y>
+ inline nullable<T>& nullable<T>::
+ operator= (const nullable<Y>& y)
{
- return value_;
+ value_ = y.value_;
+ null_ = y.null_;
+ return *this;
}
template <typename T>
- inline const T& nullable<T>::
- operator* () const
+ inline void nullable<T>::
+ swap (nullable& y)
{
- return value_;
+ T v (value_);
+ bool n (null_);
+
+ value_ = y.value_;
+ null_ = y.null_;
+
+ y.value_ = v;
+ y.null_ = n;
}
template <typename T>
@@ -222,6 +483,8 @@ namespace odb
value_ = T ();
null_ = true;
}
+
+#endif
}
#include <odb/post.hxx>