diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2014-08-01 07:15:19 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2014-08-01 11:06:50 +0200 |
commit | 18aeb349f502bfdf3ddc64e6a3f671a0a818a3f3 (patch) | |
tree | 6a97c7b27f1387c8e902b3efd192b1557f9dea63 | |
parent | fd3f1c89d75950c3603661a7255866d680ec5033 (diff) |
Add support for defining persistent objects as class template instantiations
-rw-r--r-- | NEWS | 5 | ||||
-rw-r--r-- | doc/manual.xhtml | 88 | ||||
-rw-r--r-- | odb/common.cxx | 4 | ||||
-rw-r--r-- | odb/common.hxx | 3 |
4 files changed, 97 insertions, 3 deletions
@@ -4,6 +4,11 @@ Version 2.4.0 (translated to the ON DELETE SQL clause) for an object pointer. For more information, refer to Section 14.4.15, "on_delete" in the ODB manual. + * Support for defining persistent objects as instantiations of C++ class + templates, similar to composite value types. For details, refer to + Section 15.2, "Persistent Class Template Instantiations" in the ODB + manual. + * User-supplied prologues and epilogues are now generated outside the pre.hxx/post.hxx includes. This allows the use of precompiled headers with the generated files. diff --git a/doc/manual.xhtml b/doc/manual.xhtml index 06d7c82..57b95af 100644 --- a/doc/manual.xhtml +++ b/doc/manual.xhtml @@ -664,6 +664,7 @@ for consistency. <th>15</th><td><a href="#15">Advanced Techniques and Mechanisms</a> <table class="toc"> <tr><th>15.1</th><td><a href="#15.1">Transaction Callbacks</a></td></tr> + <tr><th>15.2</th><td><a href="#15.2">Persistent Class Template Instantiations</a></td></tr> </table> </td> </tr> @@ -17931,6 +17932,93 @@ class object }; </pre> + <h2><a name="15.2">15.2 Persistent Class Template Instantiations</a></h2> + + <p>Similar to composite value types (<a href="#7.2">Section 7.2, "Composite + Value Types"</a>), a persistent object can be defined as an instantiation + of a C++ class template, for example:</p> + + <pre class="cxx"> +template <typename T> +class person +{ + ... + + T first_; + T last_; +}; + +typedef person<std::string> std_person; + +#pragma db object(std_person) +#pragma db member(std_person::last_) id + </pre> + + <p>Note that the database support code for such a persistent object + is generated when compiling the header containing the + <code>db object</code> pragma and not the header containing + the template definition or the <code>typedef</code> name. This + allows us to use templates defined in other files, for example:</p> + + <pre class="cxx"> +#include <utility> // std::pair + +typedef std::pair<unsigned int, std::string> person; +#pragma db object(person) +#pragma db member(person::first) id auto column("id") +#pragma db member(person::second) column("name") + </pre> + + <p>You may also have to explicitly specify the object type in + calls to certain <code>database</code> class functions due + to the inability do distinguish, at the API level, between + smart pointers and persistent objects defined as class + template instantiations. For example:</p> + + <pre class="cxx"> +person p; + +db.update (p); // Error. +db.reload (p); // Error. +db.erase (p); // Error. + +db.update<person> (p); // Ok. +db.reload<person> (p); // Ok. +db.erase<person> (p); // Ok. + </pre> + + <p>It also makes sense to factor persistent data members that do not + depend on template arguments into a common, non-template base class. + The following more realistic example illustrates this approach:</p> + + <pre class="cxx"> +#pragma db object abstract +class base_common +{ + ... + + #pragma db id auto + unsigned long id; +}; + +template <typename T> +class base: public base_common +{ + ... + + T value; +}; + +typedef base<std::string> string_base; +#pragma db object(string_base) abstract + +#pragma db object +class derived: public string_base +{ + ... +}; + </pre> + <!-- PART --> diff --git a/odb/common.cxx b/odb/common.cxx index f52cee6..b75d323 100644 --- a/odb/common.cxx +++ b/odb/common.cxx @@ -504,9 +504,9 @@ check (semantics::typedefs& t) if (ci == 0) return false; - // It must be a composite value. + // It must be an object or composite value. // - if (!composite (*ci)) + if (!object (*ci) && !composite (*ci)) return false; // This typedef name should be the one that was used in the pragma. diff --git a/odb/common.hxx b/odb/common.hxx index 0fcd481..6e70f43 100644 --- a/odb/common.hxx +++ b/odb/common.hxx @@ -420,7 +420,8 @@ private: columns columns_; }; -// Traverse composite values that are class template instantiations. +// Traverse objects and composite values that are class template +// instantiations. // struct typedefs: traversal::typedefs, context { |