From 2528431334b0c8aa07c85ec798be5fc9eb5b2add Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Sat, 3 Mar 2012 15:51:56 +0200 Subject: Documentation updates for C++11 support --- NEWS | 20 +++++ doc/manual.xhtml | 219 +++++++++++++++++++++++++++++++++++-------------------- 2 files changed, 159 insertions(+), 80 deletions(-) diff --git a/NEWS b/NEWS index b0453dd..f2ec0fd 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,25 @@ Version 1.9.0 + * Support for C++11. Some of the newly supported C++11 standard library + components include: + - std::unique_ptr as object pointer or value wrapper + - odb::lazy_unique_ptr lazy counterpart + - std::shared_ptr/weak_ptr as object pointer or value wrapper + - odb::lazy_shared_ptr/lazy_weak_ptr lazy counterparts + - support for array, forward_list, and unordered containers + - connection factory can be passed to the database constructor as + std::unique_ptr instead of std::auto_ptr + + The ODB compiler now recognizes the --std option. Valid values for this + option are 'c++98' (default) and 'c++11'. In the runtime libraries the + C++11 support is header-only which means that the same build of a runtime + library can be used in both the C++98 and C++11 modes. On UNIX, the tests + and examples can be compiled in the C++11 mode by passing the necessary + options to turn the C++ compiler into this mode (e.g., -std=c++0x GCC + option). On Windows, the tests and examples are always built in the C++11 + mode with VC++ 10 and later. The new 'c++11' example shows ODB support + for some of the C++11 features. + * Support for composite object ids. Now a composite value type can be used to declare an object id member. For more information, refer to Section 7.2.1, "Composite Object Ids" in the ODB manual as well as the 'composite' diff --git a/doc/manual.xhtml b/doc/manual.xhtml index 92c3d9b..347c8ef 100644 --- a/doc/manual.xhtml +++ b/doc/manual.xhtml @@ -295,6 +295,7 @@ for consistency. +
1.1Architecture and Workflow
1.2Benefits
1.3Supported C++ Standards
@@ -884,12 +885,13 @@ for consistency.

In this chapter we present a high-level overview of ODB. We will start with the ODB architecture and then outline the workflow of building an application that uses ODB. We will - conclude the chapter by contrasting the drawbacks of - the traditional way of saving C++ objects to relational - databases with the benefits of using ODB for object - persistence. The next chapter takes a more hands-on approach - and shows the concrete steps necessary to implement object - persistence in a simple "Hello World" application.

+ then continue by contrasting the drawbacks of the traditional + way of saving C++ objects to relational databases with the + benefits of using ODB for object persistence. We conclude the + chapter by discussing the C++ standards supported by ODB. The + next chapter takes a more hands-on approach and shows the + concrete steps necessary to implement object persistence in + a simple "Hello World" application.

1.1 Architecture and Workflow

@@ -1042,6 +1044,15 @@ for consistency. code, is automatically generated by the ODB compiler from these declarations.

+

1.3 Supported C++ Standards

+ +

ODB provides support for ISO/IEC C++ 1998 (C++98), ISO/IEC TR 19768 + C++ Library Extensions (C++ TR1), and ISO/IEC C++ 2011 (C++11). + While the majority of the examples in this manual use C++98, + support for the new functionality and library components introduced in + TR1 and C++11 are discussed throughout the document. The c++11 + example in the odb-examples package also shows ODB + support for various C++11 features.

@@ -1776,7 +1787,8 @@ main (int argc, char* argv[]) made this object persistent. While here we use std::auto_ptr to manage the returned object, we could have also used another smart pointer, for example - shared_ptr from TR1 or Boost. For more information + std::unique_ptr from C++11 or shared_ptr + from TR1, C++11, or Boost. For more information on the object lifetime management and the smart pointers that we can use for that, see Section 3.2, "Object and View Pointers".

@@ -2279,16 +2291,18 @@ class name or object relationships. In particular, a dynamically allocated object or view that is returned as a raw pointer from a database operation can be assigned to a smart pointer of our choice, for example - std::auto_ptr or shared_ptr from TR1 or - Boost.

+ std::auto_ptr, std::unique_ptr from C++11, or + shared_ptr from TR1, C++11, or Boost.

However, to avoid any possibility of a mistake, such as forgetting to use a smart pointer for a returned object or view, as well as to simplify the use of more advanced ODB functionality, such as sessions and bidirectional object relationships, it is recommended that you use smart pointers with the sharing semantics as object and view pointers. - The shared_ptr smart pointer from TR1 or Boost is a good - default choice.

+ The shared_ptr smart pointer from TR1, C++11, or Boost + is a good default choice. However, if sharing is not required and + sessions are not used, then std::unique_ptr or + std::auto_ptr can be used just as well.

ODB provides two mechanisms for changing the object or view pointer type. We can use the --default-pointer option to specify @@ -2320,7 +2334,8 @@ class person (view)" for more information on this pragma.

Built-in support that is provided by the ODB runtime library allows us - to use the TR1 shared_ptr and std::auto_ptr as + to use shared_ptr (TR1 or C++11), + std::unique_ptr (C++11), or std::auto_ptr as pointer types. Plus, ODB profile libraries, that are available for commonly used frameworks and libraries (such as Boost and Qt), provide support for smart pointers found in these frameworks and @@ -4165,6 +4180,26 @@ namespace odb } +

In C++11 we can use the auto-typed variabe instead + of spelling the iterator type explicitly, for example:

+ +
+  for (auto i (r.begin ()); i != r.end (); ++i)
+  {
+    ...
+  }
+  
+ +

The C++11 range-based for-loop can be used to further + simplify the iteration:

+ +
+  for (person& p: r)
+  {
+    ...
+  }
+  
+

The result iterator is an input iterator which means that the only two position operations that it supports are to move to the next object and to determine whether the end of the result stream @@ -4295,10 +4330,14 @@ namespace odb

5 Containers

The ODB runtime library provides built-in persistence support for all the - commonly used standard C++ containers, namely, + commonly used standard C++98 containers, namely, std::vector, std::list, std::set, std::multiset, std::map, and - std::multimap. Plus, ODB profile libraries, that are + std::multimap as well as C++11 std::array, + std::forward_list, std::unordered_set, + std::unordered_multiset, std::unordered_map, + and std::unordered_multimap. + Plus, ODB profile libraries, that are available for commonly used frameworks and libraries (such as Boost and Qt), provide persistence support for containers found in these frameworks and libraries (Part III, "Profiles"). It is also easy @@ -4385,7 +4424,8 @@ private:

In ODB an ordered container is any container that maintains (explicitly or implicitly) an order of its elements in the form of an integer index. Standard C++ containers that are ordered include std::vector - and std::list. While elements in std::set + and std::list as well as C++11 std::array and + std::forward_list. While elements in std::set are also kept in a specific order, this order is not based on an integer index but rather on the relationship between elements. As a result, std::set is not considered an ordered @@ -4479,7 +4519,9 @@ private: or may not guarantee a particular order of the elements that it stores. Standard C++ containers that are considered set containers for the purpose of persistence include - std::set and std::multiset.

+ std::set and std::multiset as well + as C++11 std::unordered_set and + std::unordered_multiset.

The database table for a set container consists of at least two columns. The first column contains the object id of a @@ -4539,7 +4581,9 @@ private: may or may not guarantee a particular order of the elements that it stores. Standard C++ containers that are considered map containers for the purpose of persistence include - std::map and std::multimap.

+ std::map and std::multimap as well + as C++11 std::unordered_map and + std::unordered_multimap.

The database table for a map container consists of at least three columns. The first column contains the object id of a @@ -4643,7 +4687,8 @@ private:

Relationships between persistent objects are expressed with pointers or containers of pointers. The ODB runtime library provides built-in support - for the TR1 shared_ptr/weak_ptr, + for shared_ptr/weak_ptr (TR1 or C++11), + std::unique_ptr (C++11), std::auto_ptr, and raw pointers. Plus, ODB profile libraries, that available for commonly used frameworks and libraries (such as Boost and Qt), provide support for smart pointers found in these @@ -5385,13 +5430,20 @@ t.commit (); access it.

The ODB runtime library provides lazy counterparts for all the - supported pointers, namely: odb::lazy_shared_ptr and - odb::lazy_weak_ptr for TR1 shared_ptr and - weak_ptr, odb::lazy_auto_ptr for - std::auto_ptr, and odb::lazy_ptr for raw - pointers. The ODB profile libraries provide lazy pointer - implementations for smart pointers from popular frameworks and - libraries (Part III, "Profiles").

+ supported pointers, namely: + odb::lazy_shared_ptr/lazy_weak_ptr + for C++11 std::shared_ptr/weak_ptr, + odb::tr1::lazy_shared_ptr/lazy_weak_ptr + for TR1 std::tr1::shared_ptr/weak_ptr, + odb::lazy_unique_ptr for C++11 std::unique_ptr, + odb::lazy_auto_ptr for std::auto_ptr, + and odb::lazy_ptr for raw pointers. The TR1 lazy + pointers are defined in the <odb/tr1/lazy-ptr.hxx> + header while all the others — in + <odb/lazy-ptr.hxx>. The ODB profile + libraries also provide lazy pointer implementations for smart pointers + from popular frameworks and libraries (Part III, + "Profiles").

While we will discuss the interface of lazy pointers in more detail shortly, the most commonly used extra function provided by these @@ -5507,6 +5559,7 @@ public: // Query object id and database of a persistent object. // template <class O /* = T */> + // C++11: template <class O = T> object_traits<O>::id_type object_id () const; odb::database& database () const; @@ -5536,6 +5589,7 @@ for (employees::iterator i (es.begin ()); i != es.end (); ++i) lazy_weak_ptr<employee>& lwp (*i); if (lwp.object_id<employee> () < 100) + // C++11: if (lwp.object_id () < 100) { shared_ptr<employee> e (lwp.load ()); // Load and lock. cout << e->first_ << " " << e->last_ << endl; @@ -6240,8 +6294,9 @@ class person

The ODB compiler includes built-in support for using - std::auto_ptr and std::tr1::shared_ptr - as pointers to values. Plus, ODB profile libraries, that are + std::auto_ptr, std::unique_ptr (C++11), + and shared_ptr (TR1 or C++11) as pointers to values. + Plus, ODB profile libraries, that are available for commonly used frameworks and libraries (such as Boost and Qt), provide support for smart pointers found in these frameworks and libraries (Part III, "Profiles").

@@ -7717,14 +7772,14 @@ t.commit ();

The per-object caching policies depend on the object pointer kind (Section 6.4, "Using Custom Smart Pointers"). - Objects with a unique pointer, such as std::auto_ptr, - as an object pointer are never cached since it is not possible to have - two such pointers pointing to the same object. When an object is - persisted via a pointer or loaded as a dynamically allocated instance, - objects with both raw and shared pointers as object pointers are - cached. If an object is persisted as a reference or loaded into - a pre-allocated instance, the object is only cached if its object - pointer is a raw pointer.

+ Objects with a unique pointer, such as std::auto_ptr + or std::unique_ptr, as an object pointer are never + cached since it is not possible to have two such pointers pointing + to the same object. When an object is persisted via a pointer or + loaded as a dynamically allocated instance, objects with both raw + and shared pointers as object pointers are cached. If an object is + persisted as a reference or loaded into a pre-allocated instance, + the object is only cached if its object pointer is a raw pointer.

Also note that when we persist an object as a constant reference or constant pointer, the session caches such an object as @@ -11042,7 +11097,7 @@ namespace odb const char* socket = 0, const char* charset = 0, unsigned long client_flags = 0, - std::auto_ptr<connection_factory> = 0); + std::[auto|unique]_ptr<connection_factory> = 0); database (const std::string& user, const std::string& passwd, @@ -11052,7 +11107,7 @@ namespace odb const std::string* socket = 0, const std::string& charset = "", unsigned long client_flags = 0, - std::auto_ptr<connection_factory> = 0); + std::[auto|unique]_ptr<connection_factory> = 0); database (const std::string& user, const std::string* passwd, @@ -11062,7 +11117,7 @@ namespace odb const std::string* socket = 0, const std::string& charset = "", unsigned long client_flags = 0, - std::auto_ptr<connection_factory> = 0); + std::[auto|unique]_ptr<connection_factory> = 0); database (const std::string& user, const std::string& passwd, @@ -11072,7 +11127,7 @@ namespace odb const std::string& socket, const std::string& charset = "", unsigned long client_flags = 0, - std::auto_ptr<connection_factory> = 0); + std::[auto|unique]_ptr<connection_factory> = 0); database (const std::string& user, const std::string* passwd, @@ -11082,14 +11137,14 @@ namespace odb const std::string& socket, const std::string& charset = "", unsigned long client_flags = 0, - std::auto_ptr<connection_factory> = 0); + std::[auto|unique]_ptr<connection_factory> = 0); database (int& argc, char* argv[], bool erase = false, const std::string& charset = "", unsigned long client_flags = 0, - std::auto_ptr<connection_factory> = 0); + std::[auto|unique]_ptr<connection_factory> = 0); static void print_usage (std::ostream&); @@ -11188,12 +11243,12 @@ namespace odb

The static print_usage() function prints the list of options with short descriptions that are recognized by this constructor.

-

The last argument to all of the constructors is a - pointer to the connection factory. If we pass a - non-NULL value, the database instance assumes - ownership of the factory instance. The connection factory - interface as well as the available implementations are described - in the next section.

+

The last argument to all of the constructors is a pointer to the + connection factory. In C++98, it is std::auto_ptr while + in C++11 std::unique_ptr is used instead. If we pass a + non-NULL value, the database instance assumes ownership + of the factory instance. The connection factory interface as well as + the available implementations are described in the next section.

The set of accessor functions following the constructors allows us to query the parameters of the database instance.

@@ -11650,14 +11705,14 @@ namespace odb database (const std::string& name, int flags = SQLITE_OPEN_READWRITE, bool foreign_keys = true, - std::auto_ptr<connection_factory> = 0); + std::[auto|unique]_ptr<connection_factory> = 0); database (int& argc, char* argv[], bool erase = false, int flags = SQLITE_OPEN_READWRITE, bool foreign_keys = true, - std::auto_ptr<connection_factory> = 0); + std::[auto|unique]_ptr<connection_factory> = 0); static void print_usage (std::ostream&); @@ -11751,11 +11806,12 @@ auto_ptr<odb::database> db (

The static print_usage() function prints the list of options with short descriptions that are recognized by the second constructor.

-

The last argument to both constructors is a pointer to the connection - factory. If we pass a non-NULL value, the database instance - assumes ownership of the factory instance. The connection factory - interface as well as the available implementations are described - in the next section.

+

The last argument to all of the constructors is a pointer to the + connection factory. In C++98, it is std::auto_ptr while + in C++11 std::unique_ptr is used instead. If we pass a + non-NULL value, the database instance assumes ownership + of the factory instance. The connection factory interface as well as + the available implementations are described in the next section.

The set of accessor functions following the constructors allows us to query the parameters of the database instance.

@@ -12405,7 +12461,7 @@ namespace odb const std::string& host = "", unsigned int port = 0, const std::string& extra_conninfo = "", - std::auto_ptr<connection_factory> = 0); + std::[auto|unique]_ptr<connection_factory> = 0); database (const std::string& user, const std::string& password, @@ -12413,16 +12469,16 @@ namespace odb const std::string& host = "", const std::string& socket_ext = "", const std::string& extra_conninfo = "", - std::auto_ptr<connection_factory> = 0); + std::[auto|unique]_ptr<connection_factory> = 0); database (const std::string& conninfo, - std::auto_ptr<connection_factory> = 0); + std::[auto|unique]_ptr<connection_factory> = 0); database (int& argc, char* argv[], bool erase = false, const std::string& extra_conninfo = "", - std::auto_ptr<connection_factory> = 0); + std::[auto|unique]_ptr<connection_factory> = 0); static void print_usage (std::ostream&); @@ -12514,10 +12570,11 @@ namespace odb with short descriptions that are recognized by this constructor.

The last argument to all of the constructors is a pointer to the - connection factory. If we pass a non-NULL value, the - database instance assumes ownership of the factory instance. The - connection factory interface as well as the available implementations - are described in the next section.

+ connection factory. In C++98, it is std::auto_ptr while + in C++11 std::unique_ptr is used instead. If we pass a + non-NULL value, the database instance assumes ownership + of the factory instance. The connection factory interface as well as + the available implementations are described in the next section.

The set of accessor functions following the constructors allows us to query the parameters of the database instance. Note that @@ -13033,7 +13090,7 @@ namespace odb ub2 charset = 0, ub2 ncharset = 0, OCIEnv* environment = 0, - std::auto_ptr<connection_factory> = 0); + std::[auto|unique]_ptr<connection_factory> = 0); database (const std::string& user, const std::string& password, @@ -13043,7 +13100,7 @@ namespace odb ub2 charset = 0, ub2 ncharset = 0, OCIEnv* environment = 0, - std::auto_ptr<connection_factory> = 0); + std::[auto|unique]_ptr<connection_factory> = 0); database (int& argc, char* argv[], @@ -13051,7 +13108,7 @@ namespace odb ub2 charset = 0, ub2 ncharset = 0, OCIEnv* environment = 0, - std::auto_ptr<connection_factory> = 0); + std::[auto|unique]_ptr<connection_factory> = 0); static void print_usage (std::ostream&); @@ -13174,11 +13231,12 @@ namespace odb environment handle is used, then the charset and ncharset arguments have no effect.

-

The last argument to all of the constructors is a pointer to a - connection factory. If we pass a non-NULL value, the - database instance assumes ownership of the factory instance. The - connection factory interface as well as the available implementations - are described in the next section.

+

The last argument to all of the constructors is a pointer to the + connection factory. In C++98, it is std::auto_ptr while + in C++11 std::unique_ptr is used instead. If we pass a + non-NULL value, the database instance assumes ownership + of the factory instance. The connection factory interface as well as + the available implementations are described in the next section.

The set of accessor functions following the constructors allows us to query the parameters of the database instance.

@@ -13896,7 +13954,7 @@ namespace odb const std::string& driver = "", const std::string& extra_connect_string = "", SQLHENV environment = 0, - std::auto_ptr<connection_factory> = 0); + std::[auto|unique]_ptr<connection_factory> = 0); database (const std::string& user, const std::string& password, @@ -13907,7 +13965,7 @@ namespace odb const std::string& driver = "", const std::string& extra_connect_string = "", SQLHENV environment = 0, - std::auto_ptr<connection_factory> = 0); + std::[auto|unique]_ptr<connection_factory> = 0); database (const std::string& user, const std::string& password, @@ -13917,18 +13975,18 @@ namespace odb const std::string& driver = "", const std::string& extra_connect_string = "", SQLHENV environment = 0, - std::auto_ptr<connection_factory> = 0); + std::[auto|unique]_ptr<connection_factory> = 0); database (const std::string& connect_string, SQLHENV environment = 0, - std::auto_ptr<connection_factory> = 0); + std::[auto|unique]_ptr<connection_factory> = 0); database (int& argc, char* argv[], bool erase = false, const std::string& extra_connect_string = "", SQLHENV environment = 0, - std::auto_ptr<connection_factory> = 0); + std::[auto|unique]_ptr<connection_factory> = 0); static void print_usage (std::ostream&); @@ -14158,11 +14216,12 @@ odb::mssql::database dbA ("test", handle should be valid for the lifetime of the database instance.

-

The last argument to all of the constructors is a pointer to a - connection factory. If we pass a non-NULL value, the - database instance assumes ownership of the factory instance. The - connection factory interface as well as the available implementations - are described in the next section.

+

The last argument to all of the constructors is a pointer to the + connection factory. In C++98, it is std::auto_ptr while + in C++11 std::unique_ptr is used instead. If we pass a + non-NULL value, the database instance assumes ownership + of the factory instance. The connection factory interface as well as + the available implementations are described in the next section.

The set of accessor functions following the constructors allows us to query the parameters of the database instance.

-- cgit v1.1