[PATCH] D48896: [libcxx][c++17] P0083R5: Splicing Maps and Sets Part 2: merge

2018-09-12 Thread Erik Pilkington via Phabricator via cfe-commits
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

2018-09-05 Thread Erik Pilkington via Phabricator via cfe-commits
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

2018-08-21 Thread Erik Pilkington via Phabricator via cfe-commits
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

2018-08-14 Thread Erik Pilkington via Phabricator via cfe-commits
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

2018-08-07 Thread Erik Pilkington via Phabricator via cfe-commits
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

2018-07-23 Thread Erik Pilkington via Phabricator via cfe-commits
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

2018-07-03 Thread Erik Pilkington via Phabricator via cfe-commits
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);
+