[PATCH] PR78273 fix count to work with partitioning function

Jonathan Wakely jwakely@redhat.com
Wed Jan 11 14:46:00 GMT 2017


I thought it would be an optimization to use _M_find_tr(k) != end()
for the unique associative containers, but as the PR points out the
heterogeneous version of count() can find multiple matches even in a
unique container. We need to use _M_count_tr(k)  to find all matches.

	PR libstdc++/78273
	* include/bits/stl_map.h (map::count<_Kt>(const _Kt&)): Don't assume
	the heterogeneous comparison can only find one match.
	* include/bits/stl_set.h (set::count<_Kt>(const _Kt&)): Likewise.
	* testsuite/23_containers/map/operations/2.cc: Test count works with
	comparison function that just partitions rather than sorting.
	* testsuite/23_containers/set/operations/2.cc: Likewise.

Tested powerpc64le-linux, committed to trunk.

I'll also backport this to the branches.

-------------- next part --------------
commit 8e5f512a435d4ccc7b592a7c4872418943a5c9c7
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Wed Jan 11 13:49:02 2017 +0000

    PR78273 fix count to work with partitioning function
    
    	PR libstdc++/78273
    	* include/bits/stl_map.h (map::count<_Kt>(const _Kt&)): Don't assume
    	the heterogeneous comparison can only find one match.
    	* include/bits/stl_set.h (set::count<_Kt>(const _Kt&)): Likewise.
    	* testsuite/23_containers/map/operations/2.cc: Test count works with
    	comparison function that just partitions rather than sorting.
    	* testsuite/23_containers/set/operations/2.cc: Likewise.

diff --git a/libstdc++-v3/include/bits/stl_map.h b/libstdc++-v3/include/bits/stl_map.h
index f2a0ffa..91b80d9 100644
--- a/libstdc++-v3/include/bits/stl_map.h
+++ b/libstdc++-v3/include/bits/stl_map.h
@@ -1194,7 +1194,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       template<typename _Kt>
 	auto
 	count(const _Kt& __x) const -> decltype(_M_t._M_count_tr(__x))
-	{ return _M_t._M_find_tr(__x) == _M_t.end() ? 0 : 1; }
+	{ return _M_t._M_count_tr(__x); }
 #endif
       //@}
 
diff --git a/libstdc++-v3/include/bits/stl_set.h b/libstdc++-v3/include/bits/stl_set.h
index 66560a7..ab960f1 100644
--- a/libstdc++-v3/include/bits/stl_set.h
+++ b/libstdc++-v3/include/bits/stl_set.h
@@ -739,7 +739,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 	auto
 	count(const _Kt& __x) const
 	-> decltype(_M_t._M_count_tr(__x))
-	{ return _M_t._M_find_tr(__x) == _M_t.end() ? 0 : 1; }
+	{ return _M_t._M_count_tr(__x); }
 #endif
       //@}
 
diff --git a/libstdc++-v3/testsuite/23_containers/map/operations/2.cc b/libstdc++-v3/testsuite/23_containers/map/operations/2.cc
index 6509084..ef4e76b 100644
--- a/libstdc++-v3/testsuite/23_containers/map/operations/2.cc
+++ b/libstdc++-v3/testsuite/23_containers/map/operations/2.cc
@@ -133,6 +133,27 @@ test05()
   VERIFY( Cmp::count == 0);
 }
 
+void
+test06()
+{
+  // PR libstdc++/78273
+
+  struct C {
+    bool operator()(int l, int r) const { return l < r; }
+
+    struct Partition { };
+
+    bool operator()(int l, Partition) const { return l < 2; }
+    bool operator()(Partition, int r) const { return 4 < r; }
+
+    using is_transparent = void;
+  };
+
+  std::map<int, int, C> m{ {1,0}, {2,0}, {3,0}, {4, 0}, {5, 0} };
+
+  auto n = m.count(C::Partition{});
+  VERIFY( n == 3 );
+}
 
 int
 main()
@@ -142,4 +163,5 @@ main()
   test03();
   test04();
   test05();
+  test06();
 }
diff --git a/libstdc++-v3/testsuite/23_containers/set/operations/2.cc b/libstdc++-v3/testsuite/23_containers/set/operations/2.cc
index aa71ae5..aef808d 100644
--- a/libstdc++-v3/testsuite/23_containers/set/operations/2.cc
+++ b/libstdc++-v3/testsuite/23_containers/set/operations/2.cc
@@ -150,6 +150,28 @@ test06()
   s.find(i);
 }
 
+void
+test07()
+{
+  // PR libstdc++/78273
+
+  struct C {
+    bool operator()(int l, int r) const { return l < r; }
+
+    struct Partition { };
+
+    bool operator()(int l, Partition) const { return l < 2; }
+    bool operator()(Partition, int r) const { return 4 < r; }
+
+    using is_transparent = void;
+  };
+
+  std::set<int, C> s{ 1, 2, 3, 4, 5 };
+
+  auto n = s.count(C::Partition{});
+  VERIFY( n == 3 );
+}
+
 int
 main()
 {
@@ -159,4 +181,5 @@ main()
   test04();
   test05();
   test06();
+  test07();
 }


More information about the Libstdc++ mailing list