summaryrefslogtreecommitdiff
path: root/libodb/odb/traits.hxx
diff options
context:
space:
mode:
Diffstat (limited to 'libodb/odb/traits.hxx')
-rw-r--r--libodb/odb/traits.hxx317
1 files changed, 317 insertions, 0 deletions
diff --git a/libodb/odb/traits.hxx b/libodb/odb/traits.hxx
new file mode 100644
index 0000000..2c6f5d6
--- /dev/null
+++ b/libodb/odb/traits.hxx
@@ -0,0 +1,317 @@
+// file : odb/traits.hxx
+// license : GNU GPL v2; see accompanying LICENSE file
+
+#ifndef ODB_TRAITS_HXX
+#define ODB_TRAITS_HXX
+
+#include <odb/pre.hxx>
+
+#include <odb/forward.hxx>
+#include <odb/pointer-traits.hxx>
+
+namespace odb
+{
+ // Fallback dummy for non-persistent classes. It is necessary to allow
+ // the C++ compiler to instantiate persist(), etc., signatures in class
+ // database when T is a pointer (raw, smart). The overloads that use
+ // these dummy would never actually be selected by the compiler.
+ //
+ template <typename T>
+ class access::object_traits
+ {
+ // If a C++ compiler issues an error pointing to this class and saying
+ // that it is missing some declaration, then you are most likely trying
+ // to perform a database operation on a C++ type that is not a persistent
+ // object. Or you forgot to include the corresponding -odb.hxx file.
+ //
+ public:
+ struct id_type {};
+ typedef T object_type;
+ typedef T* pointer_type;
+
+ static const bool polymorphic = false;
+ };
+
+ template <typename T, typename P>
+ class access::object_factory
+ {
+ public:
+ typedef T object_type;
+ typedef P pointer_type;
+
+ static P
+ create ()
+ {
+ // By default use pointer-specific construction.
+ //
+ return pointer_factory<T, P>::create ();
+ }
+ };
+
+ template <typename T, typename P>
+ class access::view_factory
+ {
+ public:
+ typedef T view_type;
+ typedef P pointer_type;
+
+ static P
+ create ()
+ {
+ // By default use pointer-specific construction.
+ //
+ return pointer_factory<T, P>::create ();
+ }
+ };
+
+ template <typename T, typename P>
+ class access::pointer_factory
+ {
+ public:
+ typedef T value_type;
+ typedef P pointer_type;
+
+
+ // Suppress bogus use-after-free introduced in GCC 12 (GCC bug #105327).
+ //
+#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ >= 12
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wuse-after-free"
+#endif
+
+ static P
+ create ()
+ {
+ void* v (pointer_traits<P>::allocate (sizeof (T)));
+ mem_guard g (v);
+ P p (new (v) T);
+ g.release ();
+ return p;
+ }
+
+#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ >= 12
+#pragma GCC diagnostic pop
+#endif
+
+ private:
+ struct mem_guard
+ {
+ mem_guard (void* p): p_ (p) {}
+ ~mem_guard () {if (p_) pointer_traits<P>::free (p_);}
+ void release () {p_ = 0;}
+ void* p_;
+ };
+ };
+
+ //
+ // class_traits
+ //
+ enum class_kind
+ {
+ class_object,
+ class_view,
+ class_other
+ };
+
+ template <typename T>
+ struct class_traits
+ {
+ static const class_kind kind = class_other;
+ };
+
+ template <typename T>
+ struct class_traits<const T>
+ {
+ static const class_kind kind = class_traits<T>::kind;
+ };
+
+ //
+ // object_traits
+ //
+
+ template <typename T>
+ //
+ // If a C++ compiler issues an error pointing to this struct and
+ // saying that it is incomplete, then you are most likely trying to
+ // perform a database operation on a C++ type that is not a persistent
+ // object. Or you forgot to include the corresponding -odb.hxx file.
+ //
+ struct object_traits:
+ access::object_traits<T>,
+ access::object_factory<T, typename access::object_traits<T>::pointer_type>
+ {
+ typedef
+ odb::pointer_traits<typename access::object_traits<T>::pointer_type>
+ pointer_traits;
+
+ typedef typename access::object_traits<T>::object_type object_type;
+ typedef typename access::object_traits<T>::pointer_type pointer_type;
+ typedef typename pointer_traits::const_pointer_type const_pointer_type;
+ };
+
+ // Specialization for const objects. It only defines the id, object,
+ // pointer, and const_pointer types with pointer and const_pointer
+ // being the same. The idea is to only use this specialization in the
+ // interfaces, with the implementations detecting this situation and
+ // using the non-const object_traits version.
+ //
+ template <typename T>
+ struct object_traits<const T>
+ {
+ private:
+ typedef
+ odb::pointer_traits<typename access::object_traits<T>::pointer_type>
+ pointer_traits;
+
+ public:
+ typedef typename access::object_traits<T>::id_type id_type;
+ typedef typename access::object_traits<T>::object_type object_type;
+ typedef typename pointer_traits::const_pointer_type const_pointer_type;
+ typedef const_pointer_type pointer_type;
+
+ static const bool polymorphic = access::object_traits<T>::polymorphic;
+ };
+
+ // Specialization for section to allow instantiation of all the load()
+ // signature.
+ //
+ template <>
+ struct object_traits<section> {};
+
+ template <typename T, database_id DB>
+ //
+ // If a C++ compiler issues an error pointing to this struct and
+ // saying that it is incomplete, then you are most likely trying to
+ // perform a database operation on a C++ type that is not a persistent
+ // object. Or you forgot to include the corresponding -odb.hxx file.
+ //
+ struct object_traits_impl:
+ access::object_traits_impl<T, DB>,
+ access::object_factory<T, typename access::object_traits<T>::pointer_type>
+ {
+ typedef
+ odb::pointer_traits<typename access::object_traits<T>::pointer_type>
+ pointer_traits;
+
+ typedef typename access::object_traits<T>::object_type object_type;
+ typedef typename access::object_traits<T>::pointer_type pointer_type;
+ typedef typename pointer_traits::const_pointer_type const_pointer_type;
+ };
+
+ //
+ // view_traits
+ //
+
+ template <typename T>
+ //
+ // If a C++ compiler issues an error pointing to this struct and
+ // saying that it is incomplete, then you are most likely trying to
+ // perform a database operation on a C++ type that is not a view
+ // Or you forgot to include the corresponding -odb.hxx file.
+ //
+ struct view_traits:
+ access::view_traits<T>,
+ access::view_factory<T, typename access::view_traits<T>::pointer_type>
+ {
+ typedef
+ odb::pointer_traits<typename access::view_traits<T>::pointer_type>
+ pointer_traits;
+
+ typedef typename access::view_traits<T>::view_type view_type;
+ 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;
+ };
+
+ template <typename T, database_id DB>
+ //
+ // If a C++ compiler issues an error pointing to this struct and
+ // saying that it is incomplete, then you are most likely trying to
+ // perform a database operation on a C++ type that is not a view
+ // Or you forgot to include the corresponding -odb.hxx file.
+ //
+ struct view_traits_impl:
+ access::view_traits_impl<T, DB>,
+ access::view_factory<T, typename access::view_traits<T>::pointer_type>
+ {
+ typedef
+ odb::pointer_traits<typename access::view_traits<T>::pointer_type>
+ pointer_traits;
+
+ typedef typename access::view_traits<T>::view_type view_type;
+ typedef typename access::view_traits<T>::pointer_type pointer_type;
+ };
+
+ //
+ // composite_value_traits
+ //
+
+ template <typename T, database_id DB>
+ struct composite_value_traits: access::composite_value_traits<T, DB>
+ {
+ };
+
+ //
+ // Get root image from a polymorphic image chain.
+ //
+
+ template <typename T, std::size_t d>
+ struct root_image_impl
+ {
+ typedef root_image_impl<typename T::base_traits, d - 1> base_type;
+ typedef typename base_type::image_type image_type;
+
+ static image_type&
+ get (typename T::image_type& i) {return base_type::get (*i.base);}
+ };
+
+ template <typename T>
+ struct root_image_impl<T, 1>
+ {
+ typedef typename T::image_type image_type;
+
+ static image_type&
+ get (image_type& i) {return i;}
+ };
+
+ template <typename T, bool p>
+ struct root_image
+ {
+ typedef root_image_impl<T, T::depth> impl_type;
+ typedef typename impl_type::image_type image_type;
+
+ static image_type&
+ get (typename T::image_type& i) {return impl_type::get (i);}
+ };
+
+ template <typename T>
+ struct root_image<T, false>
+ {
+ typedef typename T::image_type image_type;
+
+ static image_type&
+ get (image_type& i) {return i;}
+ };
+}
+
+#include <odb/post.hxx>
+
+#endif // ODB_TRAITS_HXX