diff options
Diffstat (limited to 'libodb/odb/traits.hxx')
-rw-r--r-- | libodb/odb/traits.hxx | 317 |
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 |