From 499a78602432c4926004f859d5fe957c313adc09 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Sat, 19 Nov 2016 18:04:00 +0200 Subject: Add small_vector class template It has a (mostly) std::vector interface (it derives from it) and will store up to N elements in the same storage as the vector instance itself. --- tests/small-vector/buildfile | 8 +++ tests/small-vector/driver.cxx | 132 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 140 insertions(+) create mode 100644 tests/small-vector/buildfile create mode 100644 tests/small-vector/driver.cxx (limited to 'tests/small-vector') diff --git a/tests/small-vector/buildfile b/tests/small-vector/buildfile new file mode 100644 index 0000000..78d2d06 --- /dev/null +++ b/tests/small-vector/buildfile @@ -0,0 +1,8 @@ +# file : tests/small-vector/buildfile +# copyright : Copyright (c) 2014-2016 Code Synthesis Ltd +# license : MIT; see accompanying LICENSE file + +exe{driver}: cxx{driver} ../../butl/lib{butl} +exe{driver}: test.arguments = $src_root + +include ../../butl/ diff --git a/tests/small-vector/driver.cxx b/tests/small-vector/driver.cxx new file mode 100644 index 0000000..5b7cfa6 --- /dev/null +++ b/tests/small-vector/driver.cxx @@ -0,0 +1,132 @@ +// file : tests/small-vector/driver.cxx -*- C++ -*- +// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#include +#include +#include + +#include + +using namespace std; +using namespace butl; + +// Return if v.data() points to somewhere inside v. +// +template +inline bool +small (const small_vector& v) +{ + const void* d (v.data ()); + return d >= &v && d < (&v + 1); +} + +int +main () +{ + using vector = small_vector; + + { + vector v; + assert (v.capacity () == 1 && small (v)); + + v.push_back ("abc"); + assert (v[0] == "abc" && v.capacity () == 1 && small (v)); + + string* d (v.data ()); // Small buffer... + + v.push_back ("xyz"); + assert (v[0] == "abc" && v.data () != d && !small (v)); + + v.pop_back (); + v.shrink_to_fit (); + assert (v[0] == "abc" && v.data () == d); + } + + // Allocator comparison. + // + { + vector v1, v2; + assert (v1.get_allocator () != v2.get_allocator ()); // stack/stack + + v1.assign ({"abc", "xyz"}); + assert (v1.get_allocator () != v2.get_allocator ()); // heap/stack + + v2.assign ({"abc", "xyz"}); + assert (v1.get_allocator () == v2.get_allocator ()); // heap/heap + + v1.pop_back (); + v1.shrink_to_fit (); + assert (v1.get_allocator () != v2.get_allocator ()); // stack/heap + + v2.pop_back (); + v2.shrink_to_fit (); + assert (v1.get_allocator () != v2.get_allocator ()); // stack/stack + } + + // Copy constructor. + // + { + vector s1 ({"abc"}), s2 (s1); + assert (s1 == s2 && s2.capacity () == 1 && small (s2)); + + vector l1 ({"abc", "xyz"}), l2 (l1); + assert (l1 == l2 && !small (l2)); + } + + // Move constructor. + // + { + struct mstring: string // Move-only string. + { + mstring () = default; + explicit mstring (const char* s): string (s) {} + + mstring (mstring&&) = default; + mstring& operator= (mstring&&) = default; + + mstring (const mstring&) = delete; + mstring& operator= (const mstring&) = delete; + }; + + using vector = small_vector; + + vector s1; s1.emplace_back ("abc"); + vector s2 (move (s1)); + assert (s2[0] == "abc" && s2.capacity () == 1 && small (s2)); + + vector l1; l1.emplace_back ("abc"); l1.emplace_back ("xyz"); + vector l2 (move (l1)); + assert (l2[0] == "abc" && l2[1] == "xyz" && !small (l2)); + } + + // Other constructors. + // + + { + const char* sa[] = {"abc"}; + const char* la[] = {"abc", "xyz"}; + + vector s (sa, sa + 1); + assert (s[0] == "abc" && s.capacity () == 1 && small (s)); + + vector l (la, la + 2); + assert (l[0] == "abc" && l[1] == "xyz" && !small (l)); + } + + { + vector s (1, "abc"); + assert (s[0] == "abc" && s.capacity () == 1 && small (s)); + + vector l (2, "abc"); + assert (l[0] == "abc" && l[1] == "abc" && !small (l)); + } + + { + vector s (1); + assert (s[0] == "" && s.capacity () == 1 && small (s)); + + vector l (2); + assert (l[0] == "" && l[1] == "" && !small (l)); + } +} -- cgit v1.1