aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--odb/container-traits.hxx142
-rw-r--r--odb/details/config-vc.h2
-rw-r--r--odb/details/config.hxx4
-rw-r--r--odb/makefile1
-rw-r--r--odb/std-array-traits.hxx13
-rw-r--r--odb/std-forward-list-traits.hxx13
-rw-r--r--odb/std-list-traits.hxx13
-rw-r--r--odb/std-map-traits.hxx26
-rw-r--r--odb/std-set-traits.hxx26
-rw-r--r--odb/std-unordered-map-traits.hxx26
-rw-r--r--odb/std-unordered-set-traits.hxx26
-rw-r--r--odb/std-vector-traits.hxx13
-rw-r--r--odb/vector-impl.cxx229
-rw-r--r--odb/vector-impl.hxx222
-rw-r--r--odb/vector-impl.ixx169
-rw-r--r--odb/vector-traits.hxx104
-rw-r--r--odb/vector-traits.txx73
-rw-r--r--odb/vector.hxx546
-rw-r--r--odb/vector.ixx397
19 files changed, 1909 insertions, 136 deletions
diff --git a/odb/container-traits.hxx b/odb/container-traits.hxx
index 85cf512..18645e6 100644
--- a/odb/container-traits.hxx
+++ b/odb/container-traits.hxx
@@ -46,50 +46,82 @@ namespace odb
}
void
- insert_one (I index, const V& value) const
+ insert (I index, const V& value) const
{
- insert_one_ (index, value, data_);
+ insert_ (index, value, data_);
}
bool
- load_all (I& next_index, V& next_value) const
+ select (I& next_index, V& next_value) const
{
- return load_all_ (next_index, next_value, data_);
+ return select_ (next_index, next_value, data_);
}
void
- delete_all () const
+ delete_ () const
{
- delete_all_ (data_);
+ delete__ (data_);
}
// Implementation details.
//
public:
- typedef void (*insert_one_type) (I, const V&, void*);
- typedef bool (*load_all_type) (I&, V&, void*);
- typedef void (*delete_all_type) (void*);
-
- ordered_functions (void* data,
- insert_one_type io,
- load_all_type la,
- delete_all_type da)
- : data_ (data), insert_one_ (io), load_all_ (la), delete_all_ (da)
+ ordered_functions (void* data): data_ (data) {}
+
+ public:
+ void* data_;
+ bool ordered_;
+
+ void (*insert_) (I, const V&, void*);
+ bool (*select_) (I&, V&, void*);
+ void (*delete__) (void*);
+ };
+
+ template <typename I, typename V>
+ struct smart_ordered_functions
+ {
+ typedef I index_type;
+ typedef V value_type;
+
+ void
+ insert (I index, const V& value) const
{
+ insert_ (index, value, data_);
+ }
+
+ bool
+ select (I& next_index, V& next_value) const
+ {
+ return select_ (next_index, next_value, data_);
}
void
- ordered (bool v)
+ update (I index, const V& value) const
{
- ordered_ = v;
+ update_ (index, value, data_);
}
- private:
+ // Delete all the elements starting with the specified index. To
+ // delete everything, pass 0.
+ //
+ void
+ delete_ (I start_index) const
+ {
+ delete__ (start_index, data_);
+ }
+
+ // Implementation details.
+ //
+ public:
+ smart_ordered_functions (void* data) : data_ (data) {}
+
+ public:
void* data_;
- bool ordered_;
- insert_one_type insert_one_;
- load_all_type load_all_;
- delete_all_type delete_all_;
+
+ void (*insert_) (I, const V&, void*);
+ bool (*select_) (I&, V&, void*);
+ void (*update_) (I, const V&, void*);
+ void (*delete__) (I, void*);
};
// Set/multiset containers.
@@ -100,43 +132,34 @@ namespace odb
typedef V value_type;
void
- insert_one (const V& value) const
+ insert (const V& value) const
{
- insert_one_ (value, data_);
+ insert_ (value, data_);
}
bool
- load_all (V& next_value) const
+ select (V& next_value) const
{
- return load_all_ (next_value, data_);
+ return select_ (next_value, data_);
}
void
- delete_all () const
+ delete_ () const
{
- delete_all_ (data_);
+ delete__ (data_);
}
// Implementation details.
//
public:
- typedef void (*insert_one_type) (const V&, void*);
- typedef bool (*load_all_type) (V&, void*);
- typedef void (*delete_all_type) (void*);
-
- set_functions (void* data,
- insert_one_type io,
- load_all_type la,
- delete_all_type da)
- : data_ (data), insert_one_ (io), load_all_ (la), delete_all_ (da)
- {
- }
+ set_functions (void* data): data_ (data) {}
- private:
+ public:
void* data_;
- insert_one_type insert_one_;
- load_all_type load_all_;
- delete_all_type delete_all_;
+
+ void (*insert_) (const V&, void*);
+ bool (*select_) (V&, void*);
+ void (*delete__) (void*);
};
// Map/multimap containers.
@@ -148,43 +171,34 @@ namespace odb
typedef V value_type;
void
- insert_one (const K& key, const V& value) const
+ insert (const K& key, const V& value) const
{
- insert_one_ (key, value, data_);
+ insert_ (key, value, data_);
}
bool
- load_all (K& next_key, V& next_value) const
+ select (K& next_key, V& next_value) const
{
- return load_all_ (next_key, next_value, data_);
+ return select_ (next_key, next_value, data_);
}
void
- delete_all () const
+ delete_ () const
{
- delete_all_ (data_);
+ delete__ (data_);
}
// Implementation details.
//
public:
- typedef void (*insert_one_type) (const K&, const V&, void*);
- typedef bool (*load_all_type) (K&, V&, void*);
- typedef void (*delete_all_type) (void*);
-
- map_functions (void* data,
- insert_one_type io,
- load_all_type la,
- delete_all_type da)
- : data_ (data), insert_one_ (io), load_all_ (la), delete_all_ (da)
- {
- }
+ map_functions (void* data): data_ (data) {}
- private:
+ public:
void* data_;
- insert_one_type insert_one_;
- load_all_type load_all_;
- delete_all_type delete_all_;
+
+ void (*insert_) (const K&, const V&, void*);
+ bool (*select_) (K&, V&, void*);
+ void (*delete__) (void*);
};
}
diff --git a/odb/details/config-vc.h b/odb/details/config-vc.h
index 2c2990a..6c7ed6d 100644
--- a/odb/details/config-vc.h
+++ b/odb/details/config-vc.h
@@ -19,6 +19,8 @@
//# define ODB_CXX11_DELETED_FUNCTION
//# define ODB_CXX11_EXPLICIT_CONVERSION_OPERATOR
//# define ODB_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGUMENT
+//# define ODB_CXX11_VARIADIC_TEMPLATES
+//# define ODB_CXX11_INITIALIZER_LIST
#endif
#endif /* ODB_DETAILS_CONFIG_VC_H */
diff --git a/odb/details/config.hxx b/odb/details/config.hxx
index 36a8e3a..ddba5b7 100644
--- a/odb/details/config.hxx
+++ b/odb/details/config.hxx
@@ -20,6 +20,8 @@
# define ODB_CXX11_DELETED_FUNCTION
# define ODB_CXX11_EXPLICIT_CONVERSION_OPERATOR
# define ODB_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGUMENT
+# define ODB_CXX11_VARIADIC_TEMPLATE
+# define ODB_CXX11_INITIALIZER_LIST
# endif
#else
# include <odb/details/config.h>
@@ -35,6 +37,8 @@
# define ODB_CXX11_DELETED_FUNCTION
# define ODB_CXX11_EXPLICIT_CONVERSION_OPERATOR
# define ODB_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGUMENT
+# define ODB_CXX11_VARIADIC_TEMPLATE
+# define ODB_CXX11_INITIALIZER_LIST
# endif
#endif
diff --git a/odb/makefile b/odb/makefile
index c630e7c..ac7355a 100644
--- a/odb/makefile
+++ b/odb/makefile
@@ -8,6 +8,7 @@ cxx := \
callback.cxx \
exceptions.cxx \
database.cxx \
+vector-impl.cxx \
connection.cxx \
lazy-ptr-impl.cxx \
prepared-query.cxx \
diff --git a/odb/std-array-traits.hxx b/odb/std-array-traits.hxx
index a6cb5e3..438665a 100644
--- a/odb/std-array-traits.hxx
+++ b/odb/std-array-traits.hxx
@@ -19,7 +19,8 @@ namespace odb
class access::container_traits<std::array<V, N>>
{
public:
- static container_kind const kind = ck_ordered;
+ static const container_kind kind = ck_ordered;
+ static const bool smart = false;
typedef std::array<V, N> container_type;
@@ -33,7 +34,7 @@ namespace odb
persist (const container_type& c, const functions& f)
{
for (index_type i (0); i < N; ++i)
- f.insert_one (i, c[i]);
+ f.insert (i, c[i]);
}
static void
@@ -44,7 +45,7 @@ namespace odb
for (; more && i < N; ++i)
{
index_type dummy;
- more = f.load_all (dummy, c[i]);
+ more = f.select (dummy, c[i]);
}
assert (!more && i == N);
@@ -53,16 +54,16 @@ namespace odb
static void
update (const container_type& c, const functions& f)
{
- f.delete_all ();
+ f.delete_ ();
for (index_type i (0); i < N; ++i)
- f.insert_one (i, c[i]);
+ f.insert (i, c[i]);
}
static void
erase (const functions& f)
{
- f.delete_all ();
+ f.delete_ ();
}
};
}
diff --git a/odb/std-forward-list-traits.hxx b/odb/std-forward-list-traits.hxx
index a86524b..1e88abc 100644
--- a/odb/std-forward-list-traits.hxx
+++ b/odb/std-forward-list-traits.hxx
@@ -17,7 +17,8 @@ namespace odb
class access::container_traits<std::forward_list<V, A>>
{
public:
- static container_kind const kind = ck_ordered;
+ static const container_kind kind = ck_ordered;
+ static const bool smart = false;
typedef std::forward_list<V, A> container_type;
@@ -33,7 +34,7 @@ namespace odb
index_type i (0);
for (typename container_type::const_iterator j (c.begin ()),
e (c.end ()); j != e; ++j)
- f.insert_one (i++, *j);
+ f.insert (i++, *j);
}
static void
@@ -45,25 +46,25 @@ namespace odb
{
index_type dummy;
i = c.insert_after (i, value_type ());
- more = f.load_all (dummy, *i);
+ more = f.select (dummy, *i);
}
}
static void
update (const container_type& c, const functions& f)
{
- f.delete_all ();
+ f.delete_ ();
index_type i (0);
for (typename container_type::const_iterator j (c.begin ()),
e (c.end ()); j != e; ++j)
- f.insert_one (i++, *j);
+ f.insert (i++, *j);
}
static void
erase (const functions& f)
{
- f.delete_all ();
+ f.delete_ ();
}
};
}
diff --git a/odb/std-list-traits.hxx b/odb/std-list-traits.hxx
index 9289c67..ec570e2 100644
--- a/odb/std-list-traits.hxx
+++ b/odb/std-list-traits.hxx
@@ -17,7 +17,8 @@ namespace odb
class access::container_traits<std::list<V, A> >
{
public:
- static container_kind const kind = ck_ordered;
+ static const container_kind kind = ck_ordered;
+ static const bool smart = false;
typedef std::list<V, A> container_type;
@@ -33,7 +34,7 @@ namespace odb
index_type i (0);
for (typename container_type::const_iterator j (c.begin ()),
e (c.end ()); j != e; ++j)
- f.insert_one (i++, *j);
+ f.insert (i++, *j);
}
static void
@@ -45,25 +46,25 @@ namespace odb
{
index_type dummy;
c.push_back (value_type ());
- more = f.load_all (dummy, c.back ());
+ more = f.select (dummy, c.back ());
}
}
static void
update (const container_type& c, const functions& f)
{
- f.delete_all ();
+ f.delete_ ();
index_type i (0);
for (typename container_type::const_iterator j (c.begin ()),
e (c.end ()); j != e; ++j)
- f.insert_one (i++, *j);
+ f.insert (i++, *j);
}
static void
erase (const functions& f)
{
- f.delete_all ();
+ f.delete_ ();
}
};
}
diff --git a/odb/std-map-traits.hxx b/odb/std-map-traits.hxx
index a30b13e..7347172 100644
--- a/odb/std-map-traits.hxx
+++ b/odb/std-map-traits.hxx
@@ -19,7 +19,8 @@ namespace odb
class access::container_traits<std::map<K, V, C, A> >
{
public:
- static container_kind const kind = ck_map;
+ static const container_kind kind = ck_map;
+ static const bool smart = false;
typedef std::map<K, V, C, A> container_type;
@@ -35,7 +36,7 @@ namespace odb
{
for (typename container_type::const_iterator i (c.begin ()),
e (c.end ()); i != e; ++i)
- f.insert_one (i->first, i->second);
+ f.insert (i->first, i->second);
}
static void
@@ -47,7 +48,7 @@ namespace odb
{
key_type k;
value_type v;
- more = f.load_all (k, v);
+ more = f.select (k, v);
#ifdef ODB_CXX11
c.insert (pair_type (std::move (k), std::move (v)));
#else
@@ -59,17 +60,17 @@ namespace odb
static void
update (const container_type& c, const functions& f)
{
- f.delete_all ();
+ f.delete_ ();
for (typename container_type::const_iterator i (c.begin ()),
e (c.end ()); i != e; ++i)
- f.insert_one (i->first, i->second);
+ f.insert (i->first, i->second);
}
static void
erase (const functions& f)
{
- f.delete_all ();
+ f.delete_ ();
}
};
@@ -81,7 +82,8 @@ namespace odb
class access::container_traits<std::multimap<K, V, C, A> >
{
public:
- static container_kind const kind = ck_multimap;
+ static const container_kind kind = ck_multimap;
+ static const bool smart = false;
typedef std::multimap<K, V, C, A> container_type;
@@ -97,7 +99,7 @@ namespace odb
{
for (typename container_type::const_iterator i (c.begin ()),
e (c.end ()); i != e; ++i)
- f.insert_one (i->first, i->second);
+ f.insert (i->first, i->second);
}
static void
@@ -109,7 +111,7 @@ namespace odb
{
key_type k;
value_type v;
- more = f.load_all (k, v);
+ more = f.select (k, v);
#ifdef ODB_CXX11
c.insert (pair_type (std::move (k), std::move (v)));
#else
@@ -121,17 +123,17 @@ namespace odb
static void
update (const container_type& c, const functions& f)
{
- f.delete_all ();
+ f.delete_ ();
for (typename container_type::const_iterator i (c.begin ()),
e (c.end ()); i != e; ++i)
- f.insert_one (i->first, i->second);
+ f.insert (i->first, i->second);
}
static void
erase (const functions& f)
{
- f.delete_all ();
+ f.delete_ ();
}
};
}
diff --git a/odb/std-set-traits.hxx b/odb/std-set-traits.hxx
index e6b4853..6df5c61 100644
--- a/odb/std-set-traits.hxx
+++ b/odb/std-set-traits.hxx
@@ -19,7 +19,8 @@ namespace odb
class access::container_traits<std::set<V, C, A> >
{
public:
- static container_kind const kind = ck_set;
+ static const container_kind kind = ck_set;
+ static const bool smart = false;
typedef std::set<V, C, A> container_type;
typedef V value_type;
@@ -32,7 +33,7 @@ namespace odb
{
for (typename container_type::const_iterator i (c.begin ()),
e (c.end ()); i != e; ++i)
- f.insert_one (*i);
+ f.insert (*i);
}
static void
@@ -43,7 +44,7 @@ namespace odb
while (more)
{
value_type v;
- more = f.load_all (v);
+ more = f.select (v);
#ifdef ODB_CXX11
c.insert (std::move (v));
#else
@@ -55,17 +56,17 @@ namespace odb
static void
update (const container_type& c, const functions& f)
{
- f.delete_all ();
+ f.delete_ ();
for (typename container_type::const_iterator i (c.begin ()),
e (c.end ()); i != e; ++i)
- f.insert_one (*i);
+ f.insert (*i);
}
static void
erase (const functions& f)
{
- f.delete_all ();
+ f.delete_ ();
}
};
@@ -77,7 +78,8 @@ namespace odb
class access::container_traits<std::multiset<V, C, A> >
{
public:
- static container_kind const kind = ck_multiset;
+ static const container_kind kind = ck_multiset;
+ static const bool smart = false;
typedef std::multiset<V, C, A> container_type;
typedef V value_type;
@@ -90,7 +92,7 @@ namespace odb
{
for (typename container_type::const_iterator i (c.begin ()),
e (c.end ()); i != e; ++i)
- f.insert_one (*i);
+ f.insert (*i);
}
static void
@@ -101,7 +103,7 @@ namespace odb
while (more)
{
value_type v;
- more = f.load_all (v);
+ more = f.select (v);
#ifdef ODB_CXX11
c.insert (std::move (v));
#else
@@ -113,17 +115,17 @@ namespace odb
static void
update (const container_type& c, const functions& f)
{
- f.delete_all ();
+ f.delete_ ();
for (typename container_type::const_iterator i (c.begin ()),
e (c.end ()); i != e; ++i)
- f.insert_one (*i);
+ f.insert (*i);
}
static void
erase (const functions& f)
{
- f.delete_all ();
+ f.delete_ ();
}
};
}
diff --git a/odb/std-unordered-map-traits.hxx b/odb/std-unordered-map-traits.hxx
index 072d345..6045d4c 100644
--- a/odb/std-unordered-map-traits.hxx
+++ b/odb/std-unordered-map-traits.hxx
@@ -18,7 +18,8 @@ namespace odb
class access::container_traits<std::unordered_map<K, V, H, P, A>>
{
public:
- static container_kind const kind = ck_map;
+ static const container_kind kind = ck_map;
+ static const bool smart = false;
typedef std::unordered_map<K, V, H, P, A> container_type;
@@ -34,7 +35,7 @@ namespace odb
{
for (typename container_type::const_iterator i (c.begin ()),
e (c.end ()); i != e; ++i)
- f.insert_one (i->first, i->second);
+ f.insert (i->first, i->second);
}
static void
@@ -46,7 +47,7 @@ namespace odb
{
key_type k;
value_type v;
- more = f.load_all (k, v);
+ more = f.select (k, v);
c.insert (pair_type (std::move (k), std::move (v)));
}
}
@@ -54,17 +55,17 @@ namespace odb
static void
update (const container_type& c, const functions& f)
{
- f.delete_all ();
+ f.delete_ ();
for (typename container_type::const_iterator i (c.begin ()),
e (c.end ()); i != e; ++i)
- f.insert_one (i->first, i->second);
+ f.insert (i->first, i->second);
}
static void
erase (const functions& f)
{
- f.delete_all ();
+ f.delete_ ();
}
};
@@ -76,7 +77,8 @@ namespace odb
class access::container_traits<std::unordered_multimap<K, V, H, P, A>>
{
public:
- static container_kind const kind = ck_multimap;
+ static const container_kind kind = ck_multimap;
+ static const bool smart = false;
typedef std::unordered_multimap<K, V, H, P, A> container_type;
@@ -92,7 +94,7 @@ namespace odb
{
for (typename container_type::const_iterator i (c.begin ()),
e (c.end ()); i != e; ++i)
- f.insert_one (i->first, i->second);
+ f.insert (i->first, i->second);
}
static void
@@ -104,7 +106,7 @@ namespace odb
{
key_type k;
value_type v;
- more = f.load_all (k, v);
+ more = f.select (k, v);
c.insert (pair_type (std::move (k), std::move (v)));
}
}
@@ -112,17 +114,17 @@ namespace odb
static void
update (const container_type& c, const functions& f)
{
- f.delete_all ();
+ f.delete_ ();
for (typename container_type::const_iterator i (c.begin ()),
e (c.end ()); i != e; ++i)
- f.insert_one (i->first, i->second);
+ f.insert (i->first, i->second);
}
static void
erase (const functions& f)
{
- f.delete_all ();
+ f.delete_ ();
}
};
}
diff --git a/odb/std-unordered-set-traits.hxx b/odb/std-unordered-set-traits.hxx
index 6f8e6a8..3033519 100644
--- a/odb/std-unordered-set-traits.hxx
+++ b/odb/std-unordered-set-traits.hxx
@@ -18,7 +18,8 @@ namespace odb
class access::container_traits<std::unordered_set<V, H, P, A>>
{
public:
- static container_kind const kind = ck_set;
+ static const container_kind kind = ck_set;
+ static const bool smart = false;
typedef std::unordered_set<V, H, P, A> container_type;
typedef V value_type;
@@ -31,7 +32,7 @@ namespace odb
{
for (typename container_type::const_iterator i (c.begin ()),
e (c.end ()); i != e; ++i)
- f.insert_one (*i);
+ f.insert (*i);
}
static void
@@ -42,7 +43,7 @@ namespace odb
while (more)
{
value_type v;
- more = f.load_all (v);
+ more = f.select (v);
c.insert (std::move (v));
}
}
@@ -50,17 +51,17 @@ namespace odb
static void
update (const container_type& c, const functions& f)
{
- f.delete_all ();
+ f.delete_ ();
for (typename container_type::const_iterator i (c.begin ()),
e (c.end ()); i != e; ++i)
- f.insert_one (*i);
+ f.insert (*i);
}
static void
erase (const functions& f)
{
- f.delete_all ();
+ f.delete_ ();
}
};
@@ -72,7 +73,8 @@ namespace odb
class access::container_traits<std::unordered_multiset<V, H, P, A>>
{
public:
- static container_kind const kind = ck_multiset;
+ static const container_kind kind = ck_multiset;
+ static const bool smart = false;
typedef std::unordered_multiset<V, H, P, A> container_type;
typedef V value_type;
@@ -85,7 +87,7 @@ namespace odb
{
for (typename container_type::const_iterator i (c.begin ()),
e (c.end ()); i != e; ++i)
- f.insert_one (*i);
+ f.insert (*i);
}
static void
@@ -96,7 +98,7 @@ namespace odb
while (more)
{
value_type v;
- more = f.load_all (v);
+ more = f.select (v);
c.insert (std::move (v));
}
}
@@ -104,17 +106,17 @@ namespace odb
static void
update (const container_type& c, const functions& f)
{
- f.delete_all ();
+ f.delete_ ();
for (typename container_type::const_iterator i (c.begin ()),
e (c.end ()); i != e; ++i)
- f.insert_one (*i);
+ f.insert (*i);
}
static void
erase (const functions& f)
{
- f.delete_all ();
+ f.delete_ ();
}
};
}
diff --git a/odb/std-vector-traits.hxx b/odb/std-vector-traits.hxx
index b0a2992..381db36 100644
--- a/odb/std-vector-traits.hxx
+++ b/odb/std-vector-traits.hxx
@@ -17,7 +17,8 @@ namespace odb
class access::container_traits<std::vector<V, A> >
{
public:
- static container_kind const kind = ck_ordered;
+ static const container_kind kind = ck_ordered;
+ static const bool smart = false;
typedef std::vector<V, A> container_type;
@@ -31,7 +32,7 @@ namespace odb
persist (const container_type& c, const functions& f)
{
for (index_type i (0), n (c.size ()); i < n; ++i)
- f.insert_one (i, c[i]);
+ f.insert (i, c[i]);
}
static void
@@ -43,23 +44,23 @@ namespace odb
{
index_type dummy;
c.push_back (value_type ());
- more = f.load_all (dummy, c.back ());
+ more = f.select (dummy, c.back ());
}
}
static void
update (const container_type& c, const functions& f)
{
- f.delete_all ();
+ f.delete_ ();
for (index_type i (0), n (c.size ()); i < n; ++i)
- f.insert_one (i, c[i]);
+ f.insert (i, c[i]);
}
static void
erase (const functions& f)
{
- f.delete_all ();
+ f.delete_ ();
}
};
}
diff --git a/odb/vector-impl.cxx b/odb/vector-impl.cxx
new file mode 100644
index 0000000..9fd38f3
--- /dev/null
+++ b/odb/vector-impl.cxx
@@ -0,0 +1,229 @@
+// file : odb/vector-impl.cxx
+// copyright : Copyright (c) 2009-2012 Code Synthesis Tools CC
+// license : GNU GPL v2; see accompanying LICENSE file
+
+#include <odb/vector-impl.hxx>
+
+#include <cstring> // std::memcpy, std::memset
+
+#ifdef ODB_CXX11
+# include <utility> // std::swap, std::move
+#else
+# include <algorithm> // std::swap
+#endif
+
+#include <iostream> // @@ tmp
+
+using namespace std;
+
+namespace odb
+{
+ // vector_impl
+ //
+ const unsigned char vector_impl::mask_[4] = {0x3, 0xC, 0x30, 0xC0};
+ const unsigned char vector_impl::shift_[4] = {0, 2, 4, 6};
+
+ vector_impl::
+ vector_impl (const vector_impl& x)
+ : state_ (x.state_), size_ (0), tail_ (0), capacity_ (0), data_ (0)
+ {
+ // Copy the data over if we are tracking.
+ //
+ if (state_ == state_tracking && size_ != 0)
+ {
+ realloc (x.size_ < 1024 ? 1024 : x.size_);
+ memcpy (data_, x.data_, x.size_ / 4 + (x.size_ % 4 == 0 ? 0 : 1));
+ size_ = x.size_;
+ tail_ = x.tail_;
+ }
+ }
+
+ void vector_impl::
+ realloc (size_t n)
+ {
+ // The new capacity can be less or greater than the old one, but
+ // it cannot be less than size.
+ //
+ size_t b (n / 4 + (n % 4 == 0 ? 0 : 1));
+
+ if (b != capacity_ * 4)
+ {
+ unsigned char* d (static_cast<unsigned char*> (operator new (b)));
+
+ if (size_ != 0)
+ memcpy (d, data_, size_ / 4 + (size_ % 4 == 0 ? 0 : 1));
+
+ if (data_ != 0)
+ operator delete (data_);
+
+ data_ = d;
+ capacity_ = b * 4;
+ }
+ }
+
+ void vector_impl::
+ shrink_to_fit ()
+ {
+ if (size_ != capacity_)
+ {
+ if (size_ != 0)
+ realloc (size_);
+ else
+ {
+ operator delete (data_);
+ data_ = 0;
+ capacity_ = 0;
+ }
+ }
+ }
+
+ void vector_impl::
+ start (size_t n)
+ {
+ if (n != 0)
+ {
+ if (capacity_ < n)
+ {
+ size_ = 0;
+ realloc (n < 1024 ? 1024 : n);
+ }
+
+ memset (data_, 0, n / 4 + (n % 4 == 0 ? 0 : 1));
+ }
+
+ state_ = state_tracking;
+ size_ = tail_ = n;
+ }
+
+ void vector_impl::
+ push_back (size_t n)
+ {
+ for (; n != 0; --n)
+ {
+ size_t i (tail_);
+
+ element_state_type s;
+ if (i != size_)
+ // We have an erased element we can reuse.
+ //
+ s = state_updated;
+ else
+ {
+ if (size_ == capacity_)
+ {
+ size_t c (capacity_ == 0 ? 1024 : capacity_ * 2);
+ if (c < size_ + n)
+ c = size_ + n;
+ realloc (c);
+ }
+
+ s = state_inserted;
+ size_++;
+ }
+
+ set (i, s);
+ tail_++;
+ }
+ }
+
+ void vector_impl::
+ pop_back (size_t n)
+ {
+ for (; n != 0; --n)
+ {
+ size_t i (tail_ - 1);
+
+ if (state (i) != state_inserted)
+ set (i, state_erased);
+ else
+ size_--; // tail_ == size_
+
+ tail_--;
+ }
+ }
+
+ void vector_impl::
+ insert (size_t i, size_t n)
+ {
+ for (; i != tail_; ++i)
+ if (state (i) != state_inserted)
+ set (i, state_updated);
+
+ push_back (n);
+ }
+
+ void vector_impl::
+ erase (size_t i, size_t n)
+ {
+ pop_back (n);
+
+ for (; i != tail_; ++i)
+ if (state (i) != state_inserted)
+ set (i, state_updated);
+ }
+
+ void vector_impl::
+ clear ()
+ {
+ // The idea is to drop any inserted elements from the back and
+ // set everything else to erased.
+ //
+ if (tail_ == size_)
+ {
+ while (size_ != 0 && state (size_ - 1) == state_inserted)
+ size_--;
+
+ tail_ = size_;
+ }
+
+ if (tail_ != 0)
+ memset (data_, 0xFF, tail_ / 4 + (tail_ % 4 == 0 ? 0 : 1));
+
+ tail_ = 0;
+ }
+
+ // vector_base
+ //
+#ifdef ODB_CXX11
+ vector_base::
+ vector_base (vector_base&& x)
+ : impl_ (std::move (x.impl_)), tran_ (0)
+ {
+ if (x.tran_ != 0)
+ {
+ x.tran_->unregister (&x);
+ _arm (*x.tran_);
+ }
+ }
+#endif
+
+ void vector_base::
+ rollback (unsigned short, void* key, unsigned long long)
+ {
+ // Mark as changed.
+ //
+ static_cast<vector_base*> (key)->impl_.change ();
+ }
+
+ void vector_base::
+ swap_tran (vector_base& x)
+ {
+ // If either instance is armed, then we need to update the
+ // callback registration.
+ //
+ transaction* t (x.tran_);
+ if (tran_ != 0)
+ {
+ tran_->unregister (this);
+ x._arm (*tran_);
+ }
+
+ if (t != 0)
+ {
+ t->unregister (&x);
+ _arm (*t);
+ }
+
+ std::swap (tran_, x.tran_);
+ }
+}
diff --git a/odb/vector-impl.hxx b/odb/vector-impl.hxx
new file mode 100644
index 0000000..a6be505
--- /dev/null
+++ b/odb/vector-impl.hxx
@@ -0,0 +1,222 @@
+// file : odb/vector-impl.hxx
+// copyright : Copyright (c) 2009-2012 Code Synthesis Tools CC
+// license : GNU GPL v2; see accompanying LICENSE file
+
+#ifndef ODB_VECTOR_IMPL_HXX
+#define ODB_VECTOR_IMPL_HXX
+
+#include <odb/pre.hxx>
+#include <odb/details/config.hxx> // ODB_CXX11
+
+#include <new>
+#include <cstddef> // std::size_t
+
+#include <odb/transaction.hxx>
+#include <odb/details/export.hxx>
+
+namespace odb
+{
+ // Change tracking vector implementation details.
+ //
+ class LIBODB_EXPORT vector_impl
+ {
+ public:
+ enum element_state_type
+ {
+ state_unchanged,
+ state_inserted,
+ state_updated,
+ state_erased
+ };
+
+ enum container_state_type
+ {
+ state_tracking,
+ state_not_tracking,
+ state_changed // Container has changed but individual changes
+ // were not tracked.
+ };
+
+ vector_impl ();
+ ~vector_impl ();
+
+ // The copy constructor will copy the state. The idea is that the
+ // copy keeps tracking changes, just like the original.
+ //
+ vector_impl (const vector_impl&);
+
+#ifdef ODB_CXX11
+ vector_impl (vector_impl&&);
+#endif
+
+ void
+ swap (vector_impl& x);
+
+ // Allocate enough memory to store the specified number of
+ // elements.
+ //
+ void
+ reserve (std::size_t);
+
+ // Reduce capacity to size.
+ //
+ void
+ shrink_to_fit ();
+
+ // Capacity (each entry takes 2 bits).
+ //
+ std::size_t
+ capacity () const;
+
+ // (Re)start tracking changes for a vector with n elements.
+ //
+ void
+ start (std::size_t);
+
+ // Stop tracking changes.
+ //
+ void
+ stop ();
+
+ // Mark the container as changed without tracking the changes.
+ // This state is useful as a fallback mechnism for situations
+ // where the change information has been discarded (e.g., after
+ // its state has been updated in the database) but the container
+ // should remain changed (e.g., after the transaction is rolled
+ // back).
+ //
+ void
+ change ();
+
+ // Get the state of the container.
+ //
+ container_state_type
+ state () const;
+
+ // Shortcut for state() == state_tracking.
+ //
+ bool
+ tracking () const;
+
+ // Note that the returned size can be greater than the actual,
+ // parallel vector size. In this case the difference is the
+ // erased elements at the back.
+ //
+ std::size_t
+ size () const;
+
+ // Get the change state of the specified element.
+ //
+ element_state_type
+ state (std::size_t) const;
+
+ // Change notifications.
+ //
+ void
+ push_back (std::size_t n = 1);
+
+ void
+ pop_back (std::size_t n = 1);
+
+ void
+ insert (std::size_t, std::size_t n = 1);
+
+ void
+ erase (std::size_t, std::size_t n = 1);
+
+ void
+ modify (std::size_t, std::size_t n = 1);
+
+ void
+ clear ();
+
+ void
+ assign (std::size_t n);
+
+ void
+ resize (std::size_t n);
+
+ private:
+ // Assignment does not make sense (it is changing of the content).
+ //
+ vector_impl& operator= (const vector_impl&);
+
+ private:
+ void
+ realloc (std::size_t);
+
+ void
+ set (std::size_t, element_state_type);
+
+ static const unsigned char mask_[4];
+ static const unsigned char shift_[4];
+
+ container_state_type state_;
+
+ // Size, tail, and capacity are in 2-bit blocks. Size is the number
+ // of elements we have in data. Tail is the position of the first
+ // erased element at the back. If there are no erased elements, then
+ // tail is equal size. Capacity is the number of elements we can
+ // store in data.
+ //
+ std::size_t size_;
+ std::size_t tail_;
+ std::size_t capacity_;
+ unsigned char* data_;
+ };
+
+ // Base class that provides a change tracking interface and
+ // handles the rollback callback. The only function that's
+ // missing is _start() which needs to know the number of
+ // elements currently in the vector.
+ //
+ class LIBODB_EXPORT vector_base
+ {
+ public:
+ void
+ _stop () const {impl_.stop ();}
+
+ bool
+ _tracking () const {return impl_.tracking ();}
+
+ void
+ _arm (transaction& t) const;
+
+ vector_impl&
+ _impl () const {return impl_;}
+
+ private:
+ // Assignment is changing of the content.
+ //
+ vector_base& operator= (const vector_base&);
+
+ protected:
+ vector_base (): tran_ (0) {}
+ ~vector_base () {if (tran_ != 0) tran_->unregister (this);}
+ vector_base (const vector_base&);
+
+#ifdef ODB_CXX11
+ vector_base (vector_base&&);
+#endif
+
+ void
+ swap (vector_base&);
+
+ static void
+ rollback (unsigned short, void* key, unsigned long long);
+
+ private:
+ void
+ swap_tran (vector_base&);
+
+ protected:
+ mutable vector_impl impl_;
+ mutable transaction* tran_;
+ };
+}
+
+#include <odb/vector-impl.ixx>
+
+#include <odb/post.hxx>
+
+#endif // ODB_VECTOR_IMPL_HXX
diff --git a/odb/vector-impl.ixx b/odb/vector-impl.ixx
new file mode 100644
index 0000000..5a859c4
--- /dev/null
+++ b/odb/vector-impl.ixx
@@ -0,0 +1,169 @@
+// file : odb/vector-impl.ixx
+// copyright : Copyright (c) 2009-2012 Code Synthesis Tools CC
+// license : GNU GPL v2; see accompanying LICENSE file
+
+#ifdef ODB_CXX11
+# include <utility> // std::swap
+#else
+# include <algorithm> // std::swap
+#endif
+
+namespace odb
+{
+ // vector_impl
+ //
+ inline vector_impl::
+ vector_impl ()
+ : state_ (state_not_tracking),
+ size_ (0), tail_ (0), capacity_ (0), data_ (0)
+ {
+ }
+
+#ifdef ODB_CXX11
+ inline vector_impl::
+ vector_impl (vector_impl&& x)
+ : state_ (state_not_tracking),
+ size_ (0), tail_ (0), capacity_ (0), data_ (0)
+ {
+ swap (x);
+ }
+#endif
+
+ inline vector_impl::
+ ~vector_impl ()
+ {
+ if (data_ != 0)
+ operator delete (data_);
+ }
+
+ inline void vector_impl::
+ swap (vector_impl& x)
+ {
+ std::swap (state_, x.state_);
+ std::swap (size_, x.size_);
+ std::swap (tail_, x.tail_);
+ std::swap (capacity_, x.capacity_);
+ std::swap (data_, x.data_);
+ }
+
+ inline void vector_impl::
+ reserve (std::size_t n)
+ {
+ if (n > capacity_)
+ realloc (n);
+ }
+
+ inline void vector_impl::
+ stop ()
+ {
+ state_ = state_not_tracking;
+ size_ = tail_ = 0;
+ }
+
+ inline void vector_impl::
+ change ()
+ {
+ state_ = state_changed;
+ size_ = tail_ = 0;
+ }
+
+ inline vector_impl::container_state_type vector_impl::
+ state () const
+ {
+ return state_;
+ }
+
+ inline bool vector_impl::
+ tracking () const
+ {
+ return state_ == state_tracking;
+ }
+
+ inline std::size_t vector_impl::
+ size () const
+ {
+ return size_;
+ }
+
+ inline std::size_t vector_impl::
+ capacity () const
+ {
+ return capacity_;
+ }
+
+ inline vector_impl::element_state_type vector_impl::
+ state (std::size_t i) const
+ {
+ std::size_t r (i % 4);
+ unsigned char v (data_[i / 4]);
+ return static_cast<element_state_type> ((v & mask_[r]) >> shift_[r]);
+ }
+
+ inline void vector_impl::
+ modify (std::size_t i, std::size_t n)
+ {
+ for (; n != 0; --n, ++i)
+ if (state (i) != state_inserted)
+ set (i, state_updated);
+ }
+
+ inline void vector_impl::
+ assign (std::size_t n)
+ {
+ if (tail_ != 0)
+ clear ();
+
+ push_back (n);
+ }
+
+ inline void vector_impl::
+ resize (size_t n)
+ {
+ if (n < tail_)
+ pop_back (tail_ - n);
+ else if (n > tail_)
+ push_back (n - tail_);
+ }
+
+ inline void vector_impl::
+ set (std::size_t i, element_state_type s)
+ {
+ std::size_t r (i % 4);
+ i /= 4;
+ unsigned char v (static_cast<unsigned char> (s));
+ v <<= shift_[r];
+ data_[i] = (data_[i] & ~mask_[r]) | v;
+ }
+
+ // vector_base
+ //
+ inline void vector_base::
+ _arm (transaction& t) const
+ {
+ tran_ = &t;
+ t.register_ (&rollback,
+ const_cast<vector_base*> (this),
+ transaction::event_rollback,
+ 0,
+ &tran_);
+ }
+
+ inline vector_base::
+ vector_base (const vector_base& x)
+ : impl_ (x.impl_), tran_ (0)
+ {
+ // If the original is armed, then arm ourselves as well.
+ //
+ if (x.tran_ != 0)
+ _arm (*x.tran_);
+ }
+
+ inline void vector_base::
+ swap (vector_base& x)
+ {
+ impl_.swap (x.impl_);
+
+ if (tran_ != 0 || x.tran_ != 0)
+ swap_tran (x);
+ }
+}
diff --git a/odb/vector-traits.hxx b/odb/vector-traits.hxx
new file mode 100644
index 0000000..874480b
--- /dev/null
+++ b/odb/vector-traits.hxx
@@ -0,0 +1,104 @@
+// file : odb/vector-traits.hxx
+// copyright : Copyright (c) 2009-2012 Code Synthesis Tools CC
+// license : GNU GPL v2; see accompanying LICENSE file
+
+#ifndef ODB_VECTOR_TRAITS_HXX
+#define ODB_VECTOR_TRAITS_HXX
+
+#include <odb/pre.hxx>
+
+#include <odb/vector.hxx>
+#include <odb/vector-impl.hxx>
+#include <odb/container-traits.hxx>
+#include <odb/transaction.hxx>
+
+namespace odb
+{
+ template <typename V, typename A>
+ class access::container_traits<vector<V, A> >
+ {
+ public:
+ static const container_kind kind = ck_ordered;
+ static const bool smart = true;
+
+ typedef vector<V, A> container_type;
+
+ typedef V value_type;
+ typedef typename container_type::size_type index_type;
+
+ typedef smart_ordered_functions<index_type, value_type> functions;
+ typedef ordered_functions<index_type, value_type> dumb_functions;
+
+ public:
+ static void
+ persist (const container_type& c, const functions& f)
+ {
+ for (index_type i (0), n (c.size ()); i < n; ++i)
+ f.insert (i, c[i]);
+
+ // Now that this container is persistent, start tracking changes.
+ //
+ c._start ();
+ }
+
+ static void
+ load (container_type& c, bool more, const functions& f)
+ {
+ // Stop tracking changes.
+ //
+ c._stop ();
+
+ // Load.
+ //
+ c.clear ();
+ while (more)
+ {
+ index_type dummy;
+ c.push_back (value_type ());
+ more = f.select (dummy, c.modify_back ());
+ }
+
+ // Start tracking changes.
+ //
+ c._start ();
+ }
+
+ static void
+ update (const container_type&, const functions&);
+
+ static void
+ erase (const container_type* c, const functions& f)
+ {
+ f.delete_ (0);
+
+ // Stop tracking changes.
+ //
+ if (c != 0)
+ c->_stop ();
+ }
+
+ // Version of load() for dumb functions. Used to support
+ // inverse members of the container type. The implementation
+ // is identical to the smart one except we don't turn off/on
+ // change tracking.
+ //
+ static void
+ load (container_type& c, bool more, const dumb_functions& f)
+ {
+ c.clear ();
+
+ while (more)
+ {
+ index_type dummy;
+ c.push_back (value_type ());
+ more = f.select (dummy, c.modify_back ());
+ }
+ }
+ };
+}
+
+#include <odb/vector-traits.txx>
+
+#include <odb/post.hxx>
+
+#endif // ODB_VECTOR_TRAITS_HXX
diff --git a/odb/vector-traits.txx b/odb/vector-traits.txx
new file mode 100644
index 0000000..255b074
--- /dev/null
+++ b/odb/vector-traits.txx
@@ -0,0 +1,73 @@
+// file : odb/vector-traits.txx
+// copyright : Copyright (c) 2009-2012 Code Synthesis Tools CC
+// license : GNU GPL v2; see accompanying LICENSE file
+
+namespace odb
+{
+ template <typename V, typename A>
+ void access::container_traits<vector<V, A> >::
+ update (const container_type& c, const functions& f)
+ {
+ bool u (false); // Updated flag.
+
+ if (c._tracking ())
+ {
+ const vector_impl& impl (c._impl ());
+
+ for (std::size_t i (0), n (impl.size ()); i < n; ++i)
+ {
+ vector_impl::element_state_type s (impl.state (i));
+
+ switch (s)
+ {
+ case vector_impl::state_unchanged:
+ {
+ break;
+ }
+ case vector_impl::state_inserted:
+ {
+ f.insert (i, c[static_cast<index_type> (i)]);
+ u = u || true;
+ break;
+ }
+ case vector_impl::state_updated:
+ {
+ f.update (i, c[static_cast<index_type> (i)]);
+ u = u || true;
+ break;
+ }
+ case vector_impl::state_erased:
+ {
+ f.delete_ (i); // Delete from i onwards.
+ u = u || true;
+ break;
+ }
+ }
+
+ // We delete all trailing elements in one go.
+ //
+ if (s == vector_impl::state_erased)
+ break;
+ }
+ }
+ else
+ {
+ // Fall back to delete all/insert all.
+ //
+ f.delete_ (0);
+
+ for (index_type i (0), n (c.size ()); i < n; ++i)
+ f.insert (i, c[i]);
+
+ u = true;
+ }
+
+ // Arm the rollback callback and (re)start change tracking.
+ //
+ if (u)
+ {
+ c._arm (transaction::current ());
+ c._start ();
+ }
+ }
+}
diff --git a/odb/vector.hxx b/odb/vector.hxx
new file mode 100644
index 0000000..17f8653
--- /dev/null
+++ b/odb/vector.hxx
@@ -0,0 +1,546 @@
+// file : odb/vector.hxx
+// copyright : Copyright (c) 2009-2012 Code Synthesis Tools CC
+// license : GNU GPL v2; see accompanying LICENSE file
+
+#ifndef ODB_VECTOR_HXX
+#define ODB_VECTOR_HXX
+
+#include <odb/pre.hxx>
+#include <odb/details/config.hxx> // ODB_CXX11
+
+#include <vector>
+#include <iterator>
+
+#ifdef ODB_CXX11
+# include <utility> // std::move, std::forward
+# ifdef ODB_CXX11_INITIALIZER_LIST
+# include <initializer_list>
+# endif
+#endif
+
+#include <odb/vector-impl.hxx>
+
+namespace odb
+{
+ // An std::vector-like container that keeps track of changes.
+ //
+ // Note that the style and order of definitions is as appears
+ // in the standard.
+ //
+ template <class V, class I>
+ class vector_iterator;
+
+ template <class T, class A = std::allocator<T> >
+ class vector: public vector_base
+ {
+ public:
+ typedef std::vector<T, A> base_vector_type;
+ typedef typename base_vector_type::iterator base_iterator_type;
+ typedef typename base_vector_type::reverse_iterator
+ base_reverse_iterator_type;
+ // types:
+ //
+ typedef typename base_vector_type::reference reference;
+ typedef typename base_vector_type::const_reference const_reference;
+ typedef vector_iterator<vector, base_iterator_type> iterator;
+ typedef typename base_vector_type::const_iterator const_iterator;
+ typedef typename base_vector_type::size_type size_type;
+ typedef typename base_vector_type::difference_type difference_type;
+ typedef T value_type;
+ typedef A allocator_type;
+ typedef typename base_vector_type::pointer pointer;
+ typedef typename base_vector_type::const_pointer const_pointer;
+ typedef vector_iterator<vector, base_reverse_iterator_type>
+ reverse_iterator;
+ typedef typename base_vector_type::const_reverse_iterator
+ const_reverse_iterator;
+ // construct/copy/destroy:
+ //
+ explicit vector(const A& a = A()): v_ (a) {}
+ explicit vector(size_type n): v_ (n) {} // C++11
+ vector(size_type n, const T& v, const A& a = A()): v_ (n, v, a) {}
+ template <class I>
+ vector(I f, I l, const A& a = A()) : v_ (f, l, a) {}
+ vector(const vector& x): vector_base (x), v_ (x.v_) {}
+ // ~vector() {}
+ vector& operator=(const vector&);
+ template <class I>
+ void assign(I f, I l);
+ void assign(size_type n, const T& u);
+ allocator_type get_allocator() const /*noexcept*/
+ {return v_.get_allocator ();}
+
+#ifdef ODB_CXX11
+ vector(vector&& x): vector_base (std::move (x)), v_ (std::move (x.v_)) {}
+ vector(const vector& x, const A& a): vector_base (x), v_ (x.v_, a) {}
+ vector(vector&& x, const A& a)
+ : vector_base (std::move (x)), v_ (std::move (x.v_), a) {}
+ vector& operator=(vector&&);
+#ifdef ODB_CXX11_INITIALIZER_LIST
+ vector(std::initializer_list<T> il, const A& a = A()): v_ (il, a) {}
+ vector& operator=(std::initializer_list<T>);
+ void assign(std::initializer_list<T>);
+#endif
+#endif
+
+ // iterators: (all /*noexcept*/)
+ //
+ iterator begin() {return iterator (this, v_.begin ());}
+ const_iterator begin() const {return v_.begin ();}
+ iterator end() {return iterator (this, v_.end ());}
+ const_iterator end() const {return v_.end ();}
+ reverse_iterator rbegin() {return reverse_iterator (this, v_.rbegin ());}
+ const_reverse_iterator rbegin() const {return v_.rbegin ();}
+ reverse_iterator rend() {return reverse_iterator (this, v_.rend ());}
+ const_reverse_iterator rend() const {return v_.rend ();}
+
+ // Return standard vector iterators. The begin() functions mark all
+ // the elements as modified.
+ //
+ base_iterator_type mbegin ();
+ base_iterator_type mend () {return v_.end ();}
+ base_reverse_iterator_type mrbegin ();
+ base_reverse_iterator_type mrend () {return v_.rend ();}
+
+#ifdef ODB_CXX11
+ const_iterator cbegin() const {return v_.cbegin ();}
+ const_iterator cend() const {return v_.cend ();}
+ const_reverse_iterator crbegin() const {return v_.crbegin ();}
+ const_reverse_iterator crend() const {return v_.crend ();}
+#endif
+
+ // capacity:
+ //
+ size_type size() const /*noexcept*/ {return v_.size ();}
+ size_type max_size() const /*noexcept*/ {return v_.max_size ();}
+ void resize(size_type); // C++11
+ void resize(size_type, const T&);
+ size_type capacity() const /*noexcept*/ {return v_.capacity ();}
+ bool empty() const /*noexcept*/ {return v_.empty ();}
+ void reserve(size_type);
+
+#ifdef ODB_CXX11
+ void shrink_to_fit();
+#endif
+
+ // element access:
+ //
+ //reference operator[](size_type n);
+ reference modify(size_type n);
+ const_reference operator[](size_type n) const {return v_[n];}
+ //reference at(size_type n);
+ reference modify_at(size_type n);
+ const_reference at(size_type n) const {return v_.at (n);}
+ //reference front();
+ reference modify_front();
+ const_reference front() const {return v_.front ();}
+ //reference back();
+ reference modify_back();
+ const_reference back() const {return v_.back ();}
+
+ // data access:
+ //
+#ifdef ODB_CXX11
+ //T* data() noexcept;
+ T* modify_data() /*noexcept*/;
+ const T* data() const /*noexcept*/ {return v_.data ();}
+#endif
+
+ // modifiers:
+ //
+ void push_back(const T& x);
+ void pop_back();
+ iterator insert(iterator position, const T& x);
+ void insert(iterator position, size_type n, const T& x);
+ template <class I>
+ void insert(iterator position, I first, I last);
+ iterator erase(iterator position);
+ iterator erase(iterator first, iterator last);
+ void swap(vector&);
+ void clear() /*noexcept*/;
+
+#ifdef ODB_CXX11
+ // In C++11 all modifiers use const_iterator instead of iterator
+ // to represent position. However, some standard libraries (notably
+ // GCC's) still use iterator and so we will do that as well, for now.
+ //
+ void push_back(T&& x);
+ iterator insert(iterator position, T&& x);
+
+#ifdef ODB_CXX11_VARIADIC_TEMPLATE
+ template <class... Args>
+ void emplace_back(Args&&... args);
+ template <class... Args>
+ iterator emplace(iterator position, Args&&... args);
+#endif
+#endif
+
+ // Interfacing with the base vector.
+ //
+ vector (const base_vector_type& x): v_ (x) {}
+ vector& operator= (const base_vector_type&);
+ operator const base_vector_type& () const {return v_;}
+ base_vector_type& base () {return v_;}
+ const base_vector_type& base () const {return v_;}
+
+#ifdef ODB_CXX11
+ vector (base_vector_type&& x): v_ (std::move (x)) {}
+ vector& operator= (base_vector_type&&);
+#endif
+
+ // Change tracking (the rest comes from vector_base).
+ //
+ public:
+ void
+ _start () const {impl_.start (v_.size ());}
+
+ private:
+ base_vector_type v_;
+ };
+
+ namespace core
+ {
+ using odb::vector;
+ }
+
+ template <class T, class A>
+ inline bool operator==(const vector<T,A>& x, const vector<T,A>& y)
+ {return x.base () == y.base ();}
+
+ template <class T, class A>
+ inline bool operator==(const vector<T,A>& x, const std::vector<T,A>& y)
+ {return x.base () == y;}
+
+ template <class T, class A>
+ inline bool operator==(const std::vector<T,A>& x, const vector<T,A>& y)
+ {return x == y.base ();}
+
+ template <class T, class A>
+ inline bool operator< (const vector<T,A>& x, const vector<T,A>& y)
+ {return x.base () < y.base ();}
+
+ template <class T, class A>
+ inline bool operator<(const vector<T,A>& x, const std::vector<T,A>& y)
+ {return x.base () < y;}
+
+ template <class T, class A>
+ inline bool operator<(const std::vector<T,A>& x, const vector<T,A>& y)
+ {return x < y.base ();}
+
+ template <class T, class A>
+ inline bool operator!=(const vector<T,A>& x, const vector<T,A>& y)
+ {return x.base () != y.base ();}
+
+ template <class T, class A>
+ inline bool operator!=(const vector<T,A>& x, const std::vector<T,A>& y)
+ {return x.base () != y;}
+
+ template <class T, class A>
+ inline bool operator!=(const std::vector<T,A>& x, const vector<T,A>& y)
+ {return x != y.base ();}
+
+ template <class T, class A>
+ inline bool operator> (const vector<T,A>& x, const vector<T,A>& y)
+ {return x.base () > y.base ();}
+
+ template <class T, class A>
+ inline bool operator>=(const vector<T,A>& x, const vector<T,A>& y)
+ {return x.base () >= y.base ();}
+
+ template <class T, class A>
+ inline bool operator>=(const vector<T,A>& x, const std::vector<T,A>& y)
+ {return x.base () >= y;}
+
+ template <class T, class A>
+ inline bool operator>=(const std::vector<T,A>& x, const vector<T,A>& y)
+ {return x >= y.base ();}
+
+ template <class T, class A>
+ inline bool operator<=(const vector<T,A>& x, const vector<T,A>& y)
+ {return x.base () <= y.base ();}
+
+ template <class T, class A>
+ inline bool operator<=(const vector<T,A>& x, const std::vector<T,A>& y)
+ {return x.base () <= y;}
+
+ template <class T, class A>
+ inline bool operator<=(const std::vector<T,A>& x, const vector<T,A>& y)
+ {return x <= y.base ();}
+
+ template <class V, class I>
+ class vector_iterator
+ {
+ public:
+ typedef V vector_type;
+ typedef I base_iterator_type;
+ typedef typename vector_type::const_iterator const_iterator_type;
+ typedef std::iterator_traits<base_iterator_type> base_iterator_traits;
+
+ typedef typename base_iterator_traits::value_type value_type;
+ typedef typename base_iterator_traits::difference_type difference_type;
+ typedef typename base_iterator_traits::pointer pointer;
+ typedef typename base_iterator_traits::reference reference;
+ typedef typename base_iterator_traits::iterator_category iterator_category;
+
+ typedef typename vector_type::size_type size_type;
+ typedef typename vector_type::const_reference const_reference;
+ typedef typename vector_type::const_pointer const_pointer;
+
+ vector_iterator (): v_ (0), i_ () {}
+ vector_iterator (vector_type* v, const base_iterator_type& i)
+ : v_ (v), i_ (i) {}
+ operator const_iterator_type () const {return i_;}
+ base_iterator_type base () const {return i_;}
+ vector_type* vector () const {return v_;}
+
+ // Note: const_{reference,pointer}.
+ //
+ const_reference operator* () const {return *i_;}
+ const_pointer operator-> () const {return i_.operator -> ();}
+ const_reference operator[] (difference_type n) const {return i_[n];}
+
+ // Modifiers.
+ //
+ reference modify () const;
+ reference modify (difference_type n) const;
+
+ vector_iterator& operator++ () {++i_; return *this;}
+ vector_iterator operator++ (int) {return vector_iterator (v_, i_++);}
+ vector_iterator& operator-- () {--i_; return *this;}
+ vector_iterator operator-- (int) {return vector_iterator (v_, i_--);}
+
+ vector_iterator operator+ (difference_type n) const
+ {return vector_iterator (v_, i_ + n);}
+ vector_iterator& operator+= (difference_type n) {i_ += n; return *this;}
+ vector_iterator operator- (difference_type n) const
+ {return vector_iterator (v_, i_ - n);}
+ vector_iterator& operator-= (difference_type n) {i_ -= n; return *this;}
+
+ // Implementation details.
+ //
+ public:
+ base_iterator_type _base () const {return i_;} // Same as base ().
+
+ private:
+ vector_type* v_;
+ base_iterator_type i_;
+ };
+
+ template <class V, class J>
+ class vector_iterator<V, std::reverse_iterator<J> >
+ {
+ public:
+ typedef V vector_type;
+ typedef std::reverse_iterator<J> base_iterator_type;
+ typedef typename vector_type::const_reverse_iterator const_iterator_type;
+ typedef std::iterator_traits<base_iterator_type> base_iterator_traits;
+
+ typedef typename vector_type::iterator iterator_type;
+ typedef typename base_iterator_traits::value_type value_type;
+ typedef typename base_iterator_traits::difference_type difference_type;
+ typedef typename base_iterator_traits::pointer pointer;
+ typedef typename base_iterator_traits::reference reference;
+ typedef typename base_iterator_traits::iterator_category iterator_category;
+
+ typedef typename vector_type::size_type size_type;
+ typedef typename vector_type::const_reference const_reference;
+ typedef typename vector_type::const_pointer const_pointer;
+
+ vector_iterator (): v_ (0), i_ () {}
+ explicit vector_iterator (const iterator_type& i)
+ : v_ (i.vector ()), i_ (i.base ()) {}
+ vector_iterator (vector_type* v, const base_iterator_type& i)
+ : v_ (v), i_ (i) {}
+ operator const_iterator_type () const {return i_;}
+ iterator_type base () const {return iterator_type (v_, i_.base ());}
+ base_iterator_type rbase () const {return i_;}
+ vector_type* vector () const {return v_;}
+
+ // Note: const_{reference,pointer}.
+ //
+ const_reference operator* () const {return *i_;}
+ const_pointer operator-> () const {return i_.operator -> ();}
+ const_reference operator[] (difference_type n) const {return i_[n];}
+
+ // Modifiers.
+ //
+ reference modify () const;
+ reference modify (difference_type n) const;
+
+ vector_iterator& operator++ () {++i_; return *this;}
+ vector_iterator operator++ (int) {return vector_iterator (v_, i_++);}
+ vector_iterator& operator-- () {--i_; return *this;}
+ vector_iterator operator-- (int) {return vector_iterator (v_, i_--);}
+
+ vector_iterator operator+ (difference_type n) const
+ {return vector_iterator (v_, i_ + n);}
+ vector_iterator& operator+= (difference_type n) {i_ += n; return *this;}
+ vector_iterator operator- (difference_type n) const
+ {return vector_iterator (v_, i_ - n);}
+ vector_iterator& operator-= (difference_type n) {i_ -= n; return *this;}
+
+ // Implementation details.
+ //
+ public:
+ base_iterator_type _base () const {return i_;} // Same as rbase().
+
+ private:
+ vector_type* v_;
+ base_iterator_type i_;
+ };
+
+ // operator==
+ //
+ template <class V, class I>
+ inline bool
+ operator== (const vector_iterator<V, I>& x, const vector_iterator<V, I>& y)
+ {return x._base () == y._base ();}
+
+ template <class V, class I>
+ inline bool
+ operator== (const vector_iterator<V, I>& x,
+ const typename vector_iterator<V, I>::const_iterator_type& y)
+ {return x._base () == y;}
+
+ template <class V, class I>
+ inline bool
+ operator== (const typename vector_iterator<V, I>::const_iterator_type& x,
+ const vector_iterator<V, I>& y)
+ {return x == y._base ();}
+
+ // operator<
+ //
+ template <class V, class I>
+ inline bool
+ operator< (const vector_iterator<V, I>& x, const vector_iterator<V, I>& y)
+ {return x._base () < y._base ();}
+
+ template <class V, class I>
+ inline bool
+ operator< (const vector_iterator<V, I>& x,
+ const typename vector_iterator<V, I>::const_iterator_type& y)
+ {return x._base () < y;}
+
+ template <class V, class I>
+ inline bool
+ operator< (const typename vector_iterator<V, I>::const_iterator_type& x,
+ const vector_iterator<V, I>& y)
+ {return x < y._base ();}
+
+ // operator!=
+ //
+ template <class V, class I>
+ inline bool
+ operator!= (const vector_iterator<V, I>& x, const vector_iterator<V, I>& y)
+ {return x._base () != y._base ();}
+
+ template <class V, class I>
+ inline bool
+ operator!= (const vector_iterator<V, I>& x,
+ const typename vector_iterator<V, I>::const_iterator_type& y)
+ {return x._base () != y;}
+
+ template <class V, class I>
+ inline bool
+ operator!= (const typename vector_iterator<V, I>::const_iterator_type& x,
+ const vector_iterator<V, I>& y)
+ {return x != y._base ();}
+
+ // operator>
+ //
+ template <class V, class I>
+ inline bool
+ operator> (const vector_iterator<V, I>& x, const vector_iterator<V, I>& y)
+ {return x._base () > y._base ();}
+
+ template <class V, class I>
+ inline bool
+ operator> (const vector_iterator<V, I>& x,
+ const typename vector_iterator<V, I>::const_iterator_type& y)
+ {return x._base () > y;}
+
+ template <class V, class I>
+ inline bool
+ operator> (const typename vector_iterator<V, I>::const_iterator_type& x,
+ const vector_iterator<V, I>& y)
+ {return x > y._base ();}
+
+ // operator>=
+ //
+ template <class V, class I>
+ inline bool
+ operator>= (const vector_iterator<V, I>& x, const vector_iterator<V, I>& y)
+ {return x._base () >= y._base ();}
+
+ template <class V, class I>
+ inline bool
+ operator>= (const vector_iterator<V, I>& x,
+ const typename vector_iterator<V, I>::const_iterator_type& y)
+ {return x._base () >= y;}
+
+ template <class V, class I>
+ inline bool
+ operator>= (const typename vector_iterator<V, I>::const_iterator_type& x,
+ const vector_iterator<V, I>& y)
+ {return x >= y._base ();}
+
+ // operator<=
+ //
+ template <class V, class I>
+ inline bool
+ operator<= (const vector_iterator<V, I>& x, const vector_iterator<V, I>& y)
+ {return x._base () <= y._base ();}
+
+ template <class V, class I>
+ inline bool
+ operator<= (const vector_iterator<V, I>& x,
+ const typename vector_iterator<V, I>::const_iterator_type& y)
+ {return x._base () <= y;}
+
+ template <class V, class I>
+ inline bool
+ operator<= (const typename vector_iterator<V, I>::const_iterator_type& x,
+ const vector_iterator<V, I>& y)
+ {return x <= y._base ();}
+
+ // operator-
+ //
+ template <class V, class I>
+ inline typename vector_iterator<V, I>::difference_type
+ operator-(const vector_iterator<V, I>& x, const vector_iterator<V, I>& y)
+ {return x._base () - y._base ();}
+
+ template <class V, class I>
+ inline typename vector_iterator<V, I>::difference_type
+ operator-(const vector_iterator<V, I>& x,
+ const typename vector_iterator<V, I>::const_iterator_type& y)
+ {return x._base () - y;}
+
+ template <class V, class I>
+ inline typename vector_iterator<V, I>::difference_type
+ operator-(const typename vector_iterator<V, I>::const_iterator_type& x,
+ const vector_iterator<V, I>& y)
+ {return x - y._base ();}
+
+ // operator+
+ //
+ template <class V, class I>
+ inline vector_iterator<V, I>
+ operator+(typename vector_iterator<V, I>::difference_type n,
+ const vector_iterator<V, I>& x)
+ {return vector_iterator<V, I> (x.vector (), n + x._base ());}
+}
+
+namespace std
+{
+ template <class T, class A>
+ inline void swap(odb::vector<T,A>& x, odb::vector<T,A>& y) {x.swap (y);}
+}
+
+#include <odb/vector.ixx>
+
+#include <odb/vector-traits.hxx>
+
+#include <odb/post.hxx>
+
+#endif // ODB_VECTOR_HXX
diff --git a/odb/vector.ixx b/odb/vector.ixx
new file mode 100644
index 0000000..1e36fe1
--- /dev/null
+++ b/odb/vector.ixx
@@ -0,0 +1,397 @@
+// file : odb/vector.ixx
+// copyright : Copyright (c) 2009-2012 Code Synthesis Tools CC
+// license : GNU GPL v2; see accompanying LICENSE file
+
+namespace odb
+{
+ //
+ // vector
+ //
+
+ // construct/copy/destroy:
+ //
+ template <class T, class A>
+ inline vector<T, A>& vector<T, A>::
+ operator= (const vector& x)
+ {
+ v_ = x.v_;
+ if (_tracking ())
+ impl_.assign (v_.size ());
+ return *this;
+ }
+
+ template <class T, class A>
+ template <class I>
+ inline void vector<T, A>::
+ assign (I f, I l)
+ {
+ v_.assign (f, l);
+ if (_tracking ())
+ impl_.assign (v_.size ());
+ }
+
+ template <class T, class A>
+ inline void vector<T, A>::
+ assign (size_type n, const T& u)
+ {
+ v_.assign (n, u);
+ if (_tracking ())
+ impl_.assign (n);
+ }
+
+#ifdef ODB_CXX11
+ template <class T, class A>
+ inline vector<T, A>& vector<T, A>::
+ vector& operator=(vector&& x)
+ {
+ v_ = std::move (x.v_);
+ if (_tracking ())
+ impl_.assign (v_.size ());
+ return *this;
+ }
+
+#ifdef ODB_CXX11_INITIALIZER_LIST
+ template <class T, class A>
+ inline vector<T, A>& vector<T, A>::
+ operator= (std::initializer_list<T> il)
+ {
+ v_ = il;
+ if (_tracking ())
+ impl_.assign (v_.size ());
+ return *this;
+ }
+
+ template <class T, class A>
+ inline void vector<T, A>::
+ assign (std::initializer_list<T> il)
+ {
+ v_.assign (il);
+ if (_tracking ())
+ impl_.assign (v_.size ());
+ }
+#endif
+#endif
+
+ // iterators:
+ //
+ template <class T, class A>
+ inline typename vector<T, A>::base_iterator_type vector<T, A>::
+ mbegin ()
+ {
+ if (_tracking ())
+ impl_.modify (0, v_.size ());
+ return v_.begin ();
+ }
+
+ template <class T, class A>
+ inline typename vector<T, A>::base_reverse_iterator_type vector<T, A>::
+ mrbegin ()
+ {
+ if (_tracking ())
+ impl_.modify (0, v_.size ());
+ return v_.rbegin ();
+ }
+
+ // capacity:
+ //
+ template <class T, class A>
+ inline void vector<T, A>::
+ resize (size_type n)
+ {
+ v_.resize (n);
+ if (_tracking ())
+ impl_.resize (n);
+ }
+
+ template <class T, class A>
+ inline void vector<T, A>::
+ resize (size_type n, const T& c)
+ {
+ v_.resize (n, c);
+ if (_tracking ())
+ impl_.resize (n);
+ }
+
+ template <class T, class A>
+ inline void vector<T, A>::
+ reserve (size_type n)
+ {
+ v_.reserve (n);
+ if (_tracking ())
+ impl_.reserve (n);
+ }
+
+#ifdef ODB_CXX11
+ template <class T, class A>
+ inline void vector<T, A>::
+ shrink_to_fit ()
+ {
+ v_.shrink_to_fit ();
+ impl_.shrink_to_fit ();
+ }
+#endif
+
+ // element access:
+ //
+ template <class T, class A>
+ inline typename vector<T, A>::reference vector<T, A>::
+ modify (size_type n)
+ {
+ reference& r (v_[n]);
+ if (_tracking ())
+ impl_.modify (n);
+ return r;
+ }
+
+ template <class T, class A>
+ inline typename vector<T, A>::reference vector<T, A>::
+ modify_at (size_type n)
+ {
+ reference& r (v_.at (n));
+ if (_tracking ())
+ impl_.modify (n);
+ return r;
+ }
+
+ template <class T, class A>
+ inline typename vector<T, A>::reference vector<T, A>::
+ modify_front ()
+ {
+ reference& r (v_.front ());
+ if (_tracking ())
+ impl_.modify (0);
+ return r;
+ }
+
+ template <class T, class A>
+ inline typename vector<T, A>::reference vector<T, A>::
+ modify_back ()
+ {
+ reference& r (v_.back ());
+ if (_tracking ())
+ impl_.modify (v_.size () - 1);
+ return r;
+ }
+
+#ifdef ODB_CXX11
+ template <class T, class A>
+ inline T* vector<T, A>::
+ modify_data() /*noexcept*/
+ {
+ if (_tracking ())
+ impl_.modify (0, v_.size ());
+ return v_.data ();
+ }
+#endif
+
+ // modifiers:
+ //
+ template <class T, class A>
+ inline void vector<T, A>::
+ push_back (const T& x)
+ {
+ v_.push_back (x);
+ if (_tracking ())
+ impl_.push_back ();
+ }
+
+ template <class T, class A>
+ inline void vector<T, A>::
+ pop_back ()
+ {
+ v_.pop_back ();
+ if (_tracking ())
+ impl_.pop_back ();
+ }
+
+ template <class T, class A>
+ inline typename vector<T, A>::iterator vector<T, A>::
+ insert (iterator p, const T& x)
+ {
+ if (_tracking ())
+ impl_.insert (static_cast<size_type> (p.base () - v_.begin ()));
+ return iterator (this, v_.insert (p.base (), x));
+ }
+
+ template <class T, class A>
+ inline void vector<T, A>::
+ insert (iterator p, size_type n, const T& x)
+ {
+ if (_tracking ())
+ impl_.insert (static_cast<size_type> (p.base () - v_.begin ()), n);
+ v_.insert (p.base (), n, x);
+ }
+
+ template <class T, class A>
+ template <class I>
+ inline void vector<T, A>::
+ insert (iterator p, I f, I l)
+ {
+ size_type i, n;
+ if (_tracking ())
+ {
+ i = static_cast<size_type> (p.base () - v_.begin ());
+ n = v_.size ();
+ }
+
+ v_.insert (p.base (), f, l);
+
+ if (_tracking ())
+ impl_.insert (i, v_.size () - n);
+ }
+
+ template <class T, class A>
+ inline typename vector<T, A>::iterator vector<T, A>::
+ erase (iterator p)
+ {
+ if (_tracking ())
+ impl_.erase (static_cast<size_type> (p.base () - v_.begin ()));
+ return iterator (this, v_.erase (p.base ()));
+ }
+
+ template <class T, class A>
+ inline typename vector<T, A>::iterator vector<T, A>::
+ erase (iterator f, iterator l)
+ {
+ if (_tracking ())
+ impl_.erase (static_cast<size_type> (f.base () - v_.begin ()),
+ static_cast<size_type> (l - f));
+ return iterator (this, v_.erase (f.base (), l.base ()));
+ }
+
+ template <class T, class A>
+ inline void vector<T, A>::
+ swap (vector& x)
+ {
+ v_.swap (x.v_);
+ vector_base::swap (x);
+ }
+
+ template <class T, class A>
+ inline void vector<T, A>::
+ clear ()
+ {
+ v_.clear ();
+ if (_tracking ())
+ impl_.clear ();
+ }
+
+#ifdef ODB_CXX11
+ template <class T, class A>
+ inline void vector<T, A>::
+ push_back(T&& x)
+ {
+ v_.push_back (std::move (x));
+ if (_tracking ())
+ impl_.push_back ();
+ }
+
+ template <class T, class A>
+ inline typename vector<T, A>::iterator vector<T, A>::
+ insert (iterator p, T&& x)
+ {
+ base_iterator_type r (v_.insert (p.base (), std::move (x)));
+ if (_tracking ())
+ impl_.insert (static_cast<size_type> (r - v_.begin ()));
+ return iterator (this, r);
+ }
+
+#ifdef ODB_CXX11_VARIADIC_TEMPLATE
+ template <class T, class A>
+ template <class... Args>
+ inline void vector<T, A>::
+ emplace_back (Args&&... args)
+ {
+ v_.push_back (std::forward<Args> (args)...);
+ if (_tracking ())
+ impl_.push_back ();
+ }
+
+ template <class T, class A>
+ template <class... Args>
+ inline typename vector<T, A>::iterator vector<T, A>::
+ emplace (iterator p, Args&&... args)
+ {
+ base_iterator_type r (
+ v_.emplace (p.base (), std::forward<Args> (args)...));
+ if (_tracking ())
+ impl_.insert (static_cast<size_type> (r - v_.begin ()));
+ return iterator (this, r);
+ }
+#endif
+#endif
+
+ // Interfacing with base vector.
+ //
+ template <class T, class A>
+ inline vector<T, A>& vector<T, A>::
+ operator= (const base_vector_type& x)
+ {
+ v_ = x;
+ if (_tracking ())
+ impl_.assign (v_.size ());
+ return *this;
+ }
+
+#ifdef ODB_CXX11
+ template <class T, class A>
+ inline vector<T, A>& vector<T, A>::
+ operator= (base_vector_type&& x)
+ {
+ v_ = std::move (x);
+ if (_tracking ())
+ impl_.assign (v_.size ());
+ return *this;
+ }
+#endif
+
+ //
+ // vector_iterator
+ //
+
+ template <class V, class I>
+ inline typename vector_iterator<V, I>::reference vector_iterator<V, I>::
+ modify () const
+ {
+ if (v_->_tracking ())
+ v_->_impl ().modify (static_cast<size_type> (i_ - v_->base ().begin ()));
+ return *i_;
+ }
+
+ template <class V, class I>
+ inline typename vector_iterator<V, I>::reference vector_iterator<V, I>::
+ modify (difference_type n) const
+ {
+ if (v_->_tracking ())
+ v_->_impl ().modify (
+ static_cast<size_type> (i_ - v_->base ().begin () + n));
+ return i_[n];
+ }
+
+ //
+ // vector_iterator<std::reverse_iterator>
+ //
+
+ template <class V, class J>
+ inline typename vector_iterator<V, std::reverse_iterator<J> >::reference
+ vector_iterator<V, std::reverse_iterator<J> >::
+ modify () const
+ {
+ if (v_->_tracking ())
+ v_->_impl ().modify (
+ static_cast<size_type> (v_->base ().rend () - i_ - 1));
+ return *i_;
+ }
+
+ template <class V, class J>
+ inline typename vector_iterator<V, std::reverse_iterator<J> >::reference
+ vector_iterator<V, std::reverse_iterator<J> >::
+ modify (difference_type n) const
+ {
+ if (v_->_tracking ())
+ // Note: going in the opposite direction.
+ v_->_impl ().modify (
+ static_cast<size_type> (v_->base ().rend () - i_ - 1 - n));
+ return i_[n];
+ }
+}