[PATCH] D48896: [libcxx][c++17] P0083R5: Splicing Maps and Sets Part 2: merge
erik.pilkington added a comment. Ping! https://reviews.llvm.org/D48896 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D48896: [libcxx][c++17] P0083R5: Splicing Maps and Sets Part 2: merge
erik.pilkington updated this revision to Diff 164064. erik.pilkington added a comment. Ping! In the new patch: - Uncomment __cpp_lib_node_extract, reverting r340544 - Rebase/Clean up the diff a bit https://reviews.llvm.org/D48896 Files: libcxx/include/__hash_table libcxx/include/__node_handle libcxx/include/__tree libcxx/include/map libcxx/include/set libcxx/include/unordered_map libcxx/include/unordered_set libcxx/test/std/containers/associative/map/map.modifiers/merge.pass.cpp libcxx/test/std/containers/associative/multimap/multimap.modifiers/merge.pass.cpp libcxx/test/std/containers/associative/multiset/merge.pass.cpp libcxx/test/std/containers/associative/set/merge.pass.cpp libcxx/test/std/containers/unord/unord.map/unord.map.modifiers/merge.pass.cpp libcxx/test/std/containers/unord/unord.multimap/unord.multimap.modifiers/merge.pass.cpp libcxx/test/std/containers/unord/unord.multiset/merge.pass.cpp libcxx/test/std/containers/unord/unord.set/merge.pass.cpp Index: libcxx/test/std/containers/unord/unord.set/merge.pass.cpp === --- /dev/null +++ libcxx/test/std/containers/unord/unord.set/merge.pass.cpp @@ -0,0 +1,135 @@ +//===--===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===--===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// + +// class unordered_set + +// template +// void merge(unordered_set& source); + +#include +#include "test_macros.h" +#include "Counter.h" + +template +bool set_equal(const Set& set, Set other) +{ +return set == other; +} + +#ifndef TEST_HAS_NO_EXCEPTIONS +template +struct throw_hasher +{ +bool& should_throw_; + +throw_hasher(bool& should_throw) : should_throw_(should_throw) {} + +typedef size_t result_type; +typedef T argument_type; + +size_t operator()(const T& p) const +{ +if (should_throw_) +throw 0; +return std::hash()(p); +} +}; +#endif + +int main() +{ +{ +std::unordered_set src{1, 3, 5}; +std::unordered_set dst{2, 4, 5}; +dst.merge(src); +assert(set_equal(src, {5})); +assert(set_equal(dst, {1, 2, 3, 4, 5})); +} + +#ifndef TEST_HAS_NO_EXCEPTIONS +{ +bool do_throw = false; +typedef std::unordered_set, throw_hasher>> set_type; +set_type src({1, 3, 5}, 0, throw_hasher>(do_throw)); +set_type dst({2, 4, 5}, 0, throw_hasher>(do_throw)); + +assert(Counter_base::gConstructed == 6); + +do_throw = true; +try +{ +dst.merge(src); +} +catch (int) +{ +do_throw = false; +} +assert(!do_throw); +assert(set_equal(src, set_type({1, 3, 5}, 0, throw_hasher>(do_throw; +assert(set_equal(dst, set_type({2, 4, 5}, 0, throw_hasher>(do_throw; +} +#endif +assert(Counter_base::gConstructed == 0); +struct equal +{ +equal() = default; + +bool operator()(const Counter& lhs, const Counter& rhs) const +{ +return lhs == rhs; +} +}; +struct hasher +{ +hasher() = default; +typedef Counter argument_type; +typedef size_t result_type; +size_t operator()(const Counter& p) const { return std::hash>()(p); } +}; +{ +typedef std::unordered_set, std::hash>, std::equal_to>> first_set_type; +typedef std::unordered_set, hasher, equal> second_set_type; +typedef std::unordered_multiset, hasher, equal> third_set_type; + +first_set_type first{1, 2, 3}; +second_set_type second{2, 3, 4}; +third_set_type third{1, 3}; + +assert(Counter_base::gConstructed == 8); + +first.merge(second); +first.merge(std::move(second)); +first.merge(third); +first.merge(std::move(third)); + +assert(set_equal(first, {1, 2, 3, 4})); +assert(set_equal(second, {2, 3})); +assert(set_equal(third, {1, 3})); + +assert(Counter_base::gConstructed == 8); +} +assert(Counter_base::gConstructed == 0); +{ +std::unordered_set first; +{ +std::unordered_set second; +first.merge(second); +first.merge(std::move(second)); +} +{ +std::unordered_multiset second; +first.merge(second); +first.merge(std::move(second)); +} +} +} Index: libcxx/test/std/containers/unord/unord.multiset/merge.pass.cpp === --- /dev/null +++ libcxx/test/std/containers/unord/unord.multiset/merge.pass.cpp @@ -0,0 +1,135
[PATCH] D48896: [libcxx][c++17] P0083R5: Splicing Maps and Sets Part 2: merge
erik.pilkington added a comment. Ping! https://reviews.llvm.org/D48896 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D48896: [libcxx][c++17] P0083R5: Splicing Maps and Sets Part 2: merge
erik.pilkington added a comment. Ping! https://reviews.llvm.org/D48896 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D48896: [libcxx][c++17] P0083R5: Splicing Maps and Sets Part 2: merge
erik.pilkington added a comment. Ping! https://reviews.llvm.org/D48896 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D48896: [libcxx][c++17] P0083R5: Splicing Maps and Sets Part 2: merge
erik.pilkington updated this revision to Diff 156912. erik.pilkington added a comment. In this new patch: - Rebase on top of changes in https://reviews.llvm.org/D46845 - Move in some forward decls that I accidentally left in https://reviews.llvm.org/D46845 - Add some missing visibility attributes - Add `merge` to header summaries https://reviews.llvm.org/D48896 Files: libcxx/include/__hash_table libcxx/include/__tree libcxx/include/map libcxx/include/set libcxx/include/unordered_map libcxx/include/unordered_set libcxx/test/std/containers/associative/map/map.modifiers/merge.pass.cpp libcxx/test/std/containers/associative/multimap/multimap.modifiers/merge.pass.cpp libcxx/test/std/containers/associative/multiset/merge.pass.cpp libcxx/test/std/containers/associative/set/merge.pass.cpp libcxx/test/std/containers/unord/unord.map/unord.map.modifiers/merge.pass.cpp libcxx/test/std/containers/unord/unord.multimap/unord.multimap.modifiers/merge.pass.cpp libcxx/test/std/containers/unord/unord.multiset/merge.pass.cpp libcxx/test/std/containers/unord/unord.set/merge.pass.cpp Index: libcxx/test/std/containers/unord/unord.set/merge.pass.cpp === --- /dev/null +++ libcxx/test/std/containers/unord/unord.set/merge.pass.cpp @@ -0,0 +1,135 @@ +//===--===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===--===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// + +// class unordered_set + +// template +// void merge(unordered_set& source); + +#include +#include "test_macros.h" +#include "Counter.h" + +template +bool set_equal(const Set& set, Set other) +{ +return set == other; +} + +#ifndef TEST_HAS_NO_EXCEPTIONS +template +struct throw_hasher +{ +bool& should_throw_; + +throw_hasher(bool& should_throw) : should_throw_(should_throw) {} + +typedef size_t result_type; +typedef T argument_type; + +size_t operator()(const T& p) const +{ +if (should_throw_) +throw 0; +return std::hash()(p); +} +}; +#endif + +int main() +{ +{ +std::unordered_set src{1, 3, 5}; +std::unordered_set dst{2, 4, 5}; +dst.merge(src); +assert(set_equal(src, {5})); +assert(set_equal(dst, {1, 2, 3, 4, 5})); +} + +#ifndef TEST_HAS_NO_EXCEPTIONS +{ +bool do_throw = false; +typedef std::unordered_set, throw_hasher>> set_type; +set_type src({1, 3, 5}, 0, throw_hasher>(do_throw)); +set_type dst({2, 4, 5}, 0, throw_hasher>(do_throw)); + +assert(Counter_base::gConstructed == 6); + +do_throw = true; +try +{ +dst.merge(src); +} +catch (int) +{ +do_throw = false; +} +assert(!do_throw); +assert(set_equal(src, set_type({1, 3, 5}, 0, throw_hasher>(do_throw; +assert(set_equal(dst, set_type({2, 4, 5}, 0, throw_hasher>(do_throw; +} +#endif +assert(Counter_base::gConstructed == 0); +struct equal +{ +equal() = default; + +bool operator()(const Counter& lhs, const Counter& rhs) const +{ +return lhs == rhs; +} +}; +struct hasher +{ +hasher() = default; +typedef Counter argument_type; +typedef size_t result_type; +size_t operator()(const Counter& p) const { return std::hash>()(p); } +}; +{ +typedef std::unordered_set, std::hash>, std::equal_to>> first_set_type; +typedef std::unordered_set, hasher, equal> second_set_type; +typedef std::unordered_multiset, hasher, equal> third_set_type; + +first_set_type first{1, 2, 3}; +second_set_type second{2, 3, 4}; +third_set_type third{1, 3}; + +assert(Counter_base::gConstructed == 8); + +first.merge(second); +first.merge(std::move(second)); +first.merge(third); +first.merge(std::move(third)); + +assert(set_equal(first, {1, 2, 3, 4})); +assert(set_equal(second, {2, 3})); +assert(set_equal(third, {1, 3})); + +assert(Counter_base::gConstructed == 8); +} +assert(Counter_base::gConstructed == 0); +{ +std::unordered_set first; +{ +std::unordered_set second; +first.merge(second); +first.merge(std::move(second)); +} +{ +std::unordered_multiset second; +first.merge(second); +first.merge(std::move(second)); +} +} +} Index: libcxx/test/std/containers/unord/unord.multiset/merge.pass.cpp
[PATCH] D48896: [libcxx][c++17] P0083R5: Splicing Maps and Sets Part 2: merge
erik.pilkington created this revision. erik.pilkington added reviewers: EricWF, mclow.lists. Herald added subscribers: dexonsmith, ldionne, christof. This was originally part of https://reviews.llvm.org/D46845, but I decided to split it out to clean up the diff. From that patch's description: > In `__hash_table`, I split up the functions `__node_insert_unqiue` and > `__node_insert_multi` into 2 parts in order to implement merge. The first > part, `__node_insert_{multi,unique}_prepare` checks to see if a node already > is present in the container (as needed), and rehashes the container. This > function can forward exceptions, but doesn't mutate the node it's preparing > to insert. the `__node_insert_{multi,unique}_perform` is noexcept, but > mutates the pointers in the node to actually insert it into the container. > This allows merge to call a `_prepare` function on a node while it is in the > source container, without invalidating anything or losing nodes if an > exception is thrown. Thanks for taking a look! Erik Repository: rCXX libc++ https://reviews.llvm.org/D48896 Files: libcxx/include/__hash_table libcxx/include/__tree libcxx/include/map libcxx/include/set libcxx/include/unordered_map libcxx/include/unordered_set libcxx/test/std/containers/associative/map/map.modifiers/merge.pass.cpp libcxx/test/std/containers/associative/multimap/multimap.modifiers/merge.pass.cpp libcxx/test/std/containers/associative/multiset/merge.pass.cpp libcxx/test/std/containers/associative/set/merge.pass.cpp libcxx/test/std/containers/unord/unord.map/unord.map.modifiers/merge.pass.cpp libcxx/test/std/containers/unord/unord.multimap/unord.multimap.modifiers/merge.pass.cpp libcxx/test/std/containers/unord/unord.multiset/merge.pass.cpp libcxx/test/std/containers/unord/unord.set/merge.pass.cpp Index: libcxx/test/std/containers/unord/unord.set/merge.pass.cpp === --- /dev/null +++ libcxx/test/std/containers/unord/unord.set/merge.pass.cpp @@ -0,0 +1,135 @@ +//===--===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===--===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// + +// class unordered_set + +// template +// void merge(unordered_set& source); + +#include +#include "test_macros.h" +#include "Counter.h" + +template +bool set_equal(const Set& set, Set other) +{ +return set == other; +} + +#ifndef TEST_HAS_NO_EXCEPTIONS +template +struct throw_hasher +{ +bool& should_throw_; + +throw_hasher(bool& should_throw) : should_throw_(should_throw) {} + +typedef size_t result_type; +typedef T argument_type; + +size_t operator()(const T& p) const +{ +if (should_throw_) +throw 0; +return std::hash()(p); +} +}; +#endif + +int main() +{ +{ +std::unordered_set src{1, 3, 5}; +std::unordered_set dst{2, 4, 5}; +dst.merge(src); +assert(set_equal(src, {5})); +assert(set_equal(dst, {1, 2, 3, 4, 5})); +} + +#ifndef TEST_HAS_NO_EXCEPTIONS +{ +bool do_throw = false; +typedef std::unordered_set, throw_hasher>> set_type; +set_type src({1, 3, 5}, 0, throw_hasher>(do_throw)); +set_type dst({2, 4, 5}, 0, throw_hasher>(do_throw)); + +assert(Counter_base::gConstructed == 6); + +do_throw = true; +try +{ +dst.merge(src); +} +catch (int) +{ +do_throw = false; +} +assert(!do_throw); +assert(set_equal(src, set_type({1, 3, 5}, 0, throw_hasher>(do_throw; +assert(set_equal(dst, set_type({2, 4, 5}, 0, throw_hasher>(do_throw; +} +#endif +assert(Counter_base::gConstructed == 0); +struct equal +{ +equal() = default; + +bool operator()(const Counter& lhs, const Counter& rhs) const +{ +return lhs == rhs; +} +}; +struct hasher +{ +hasher() = default; +typedef Counter argument_type; +typedef size_t result_type; +size_t operator()(const Counter& p) const { return std::hash>()(p); } +}; +{ +typedef std::unordered_set, std::hash>, std::equal_to>> first_set_type; +typedef std::unordered_set, hasher, equal> second_set_type; +typedef std::unordered_multiset, hasher, equal> third_set_type; + +first_set_type first{1, 2, 3}; +second_set_type second{2, 3, 4}; +third_set_type third{1, 3}; + +assert(Counter_base::gConstructed == 8); + +first.merge(second); +first.merge(std::move(second)); +first.merge(third); +