From: Mark Logan Date: Fri, 3 Feb 2017 18:09:57 +0000 (-0800) Subject: Add ContainerT&& ctors to sorted_vector_map and sorted_vector_set. X-Git-Tag: v2017.03.06.00~58 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=b90498bc90c4b327fa9877d6a395c0483f4dd686;p=folly.git Add ContainerT&& ctors to sorted_vector_map and sorted_vector_set. Summary: Add ContainerT&& ctors to sorted_vector_map and sorted_vector_set, to support more efficient bulk-construction of these containers. With the prior constructors, the only way to do bulk-construction efficiently was by using the iterator constructors with a pre-sorted range. If you didn't have a presorted range, you would need to make a temporary container in order to get a sorted range. Repeatedly calling insert() without a sorted range is quadratic, hence not an option. Reviewed By: yfeldblum Differential Revision: D4491299 fbshipit-source-id: 041c546578f44ee6928c5506e8d8191092143b12 --- diff --git a/folly/sorted_vector_types.h b/folly/sorted_vector_types.h index 5d8d5344..255b4518 100644 --- a/folly/sorted_vector_types.h +++ b/folly/sorted_vector_types.h @@ -253,6 +253,22 @@ public: insert(list.begin(), list.end()); } + // Construct a sorted_vector_set by stealing the storage of a prefilled + // container. The container need not be sorted already. This supports + // bulk construction of sorted_vector_set with zero allocations, not counting + // those performed by the caller. (The iterator range constructor performs at + // least one allocation). + // + // Note that `sorted_vector_set(const ContainerT& container)` is not provided, + // since the purpose of this constructor is to avoid an unnecessary copy. + explicit sorted_vector_set( + ContainerT&& container, + const Compare& comp = Compare()) + : m_(comp, container.get_allocator()) { + std::sort(container.begin(), container.end(), value_comp()); + m_.cont_.swap(container); + } + key_compare key_comp() const { return m_; } value_compare value_comp() const { return m_; } @@ -490,6 +506,22 @@ public: insert(list.begin(), list.end()); } + // Construct a sorted_vector_map by stealing the storage of a prefilled + // container. The container need not be sorted already. This supports + // bulk construction of sorted_vector_map with zero allocations, not counting + // those performed by the caller. (The iterator range constructor performs at + // least one allocation). + // + // Note that `sorted_vector_map(const ContainerT& container)` is not provided, + // since the purpose of this constructor is to avoid an unnecessary copy. + explicit sorted_vector_map( + ContainerT&& container, + const Compare& comp = Compare()) + : m_(value_compare(comp), container.get_allocator()) { + std::sort(container.begin(), container.end(), value_comp()); + m_.cont_.swap(container); + } + key_compare key_comp() const { return m_; } value_compare value_comp() const { return m_; } diff --git a/folly/test/sorted_vector_test.cpp b/folly/test/sorted_vector_test.cpp index 474d7e96..4805be24 100644 --- a/folly/test/sorted_vector_test.cpp +++ b/folly/test/sorted_vector_test.cpp @@ -504,3 +504,22 @@ TEST(SortedVectorTypes, TestBulkInsertionMovableTypes) { vmap.insert( std::make_move_iterator(s.begin()), std::make_move_iterator(s.end())); } + +TEST(SortedVectorTypes, TestSetCreationFromVector) { + std::vector vec = {3, 1, -1, 5, 0}; + sorted_vector_set vset(std::move(vec)); + check_invariant(vset); + EXPECT_THAT(vset, testing::ElementsAreArray({-1, 0, 1, 3, 5})); +} + +TEST(SortedVectorTypes, TestMapCreationFromVector) { + std::vector> vec = { + {3, 1}, {1, 5}, {-1, 2}, {5, 3}, {0, 3}}; + sorted_vector_map vmap(std::move(vec)); + check_invariant(vmap); + auto contents = std::vector>(vmap.begin(), vmap.end()); + auto expected_contents = std::vector>({ + {-1, 2}, {0, 3}, {1, 5}, {3, 1}, {5, 3}, + }); + EXPECT_EQ(contents, expected_contents); +}