aboutsummaryrefslogtreecommitdiff
path: root/odb/traits.hxx
blob: 838373d49b3c1fb800966df50eb142d308bfa5d1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
// file      : odb/traits.hxx
// author    : Boris Kolpackov <boris@codesynthesis.com>
// copyright : Copyright (c) 2009-2011 Code Synthesis Tools CC
// 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
{
  // template <typename T>
  // class access::object_traits;
  //
  // Specializations should define the following members:
  //
  // id_type               - object id (primary key) type
  // id_type id (const T&) - get object id
  //
  // void persist (database&, T&)
  // void update (database&, T&)
  // void erase (database&, const id_type&)
  // pointer_type find (database&, const id_type&)
  // bool find (database&, const id_type&, T&)
  //
  //

  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::pointer_factory
  {
  public:
    typedef T object_type;
    typedef P pointer_type;

    static P
    create ()
    {
      void* v (pointer_traits<P>::allocate (sizeof (T)));
      mem_guard g (v);
      P p (new (v) T);
      g.release ();
      return p;
    }
  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_;
    };
  };

  template <typename T>
  struct object_traits:
    access::object_traits<T>,
    access::object_factory<T, typename access::object_traits<T>::pointer_type>
  {
    //
    // 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.
    //

    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;
  };

  // Specializations for pointer types to allow the C++ compiler to
  // instantiate persist(), etc., signatures in class database. The
  // overloads that use these specializations would never actually
  // be selected by the compiler.
  //
  template <typename T>
  struct object_traits<T*>
  {
    struct id_type {};
  };

  template <typename T>
  struct object_traits<T* const>
  {
    struct id_type {};
  };

  template <typename T, template <typename> class P>
  struct object_traits< P<T> >
  {
    struct id_type {};
  };

  template <typename T, template <typename> class P>
  struct object_traits< const P<T> >
  {
    struct id_type {};
  };

  template <typename T>
  struct composite_value_traits: access::composite_value_traits<T>
  {
  };
}

#include <odb/post.hxx>

#endif // ODB_TRAITS_HXX