[PATCH] c++: CTAD and deduction guide selection [PR86439]

Patrick Palka ppalka@redhat.com
Wed Jun 23 04:19:07 GMT 2021


On Tue, 22 Jun 2021, Jonathan Wakely wrote:

> On Tue, 22 Jun 2021 at 19:45, Patrick Palka wrote:
> > This change causes us to reject some container CTAD examples in the
> > libstdc++ testsuite due to deduction failure for {}, which AFAICT is the
> > correct behavior.  Previously, in the case of e.g. the first removed
> > example for std::map, the type of {} would be deduced to less<int> as a
> > side effect of forming the call to the selected guide
> >
> >   template<typename _Key, typename _Tp, typename _Compare = less<_Key>,
> >              typename _Allocator = allocator<pair<const _Key, _Tp>>,
> >              typename = _RequireNotAllocator<_Compare>,
> >              typename = _RequireAllocator<_Allocator>>
> >       map(initializer_list<pair<_Key, _Tp>>,
> >           _Compare = _Compare(), _Allocator = _Allocator())
> >       -> map<_Key, _Tp, _Compare, _Allocator>;
> >
> > which made later overload resolution for the constructor call
> > unambiguous.  Now, the type of {} remains undeduced until constructor
> > overload resolution, and we complain about ambiguity with the two
> > constructors
> >
> >   map(initializer_list<value_type> __l,
> >       const _Compare& __comp = _Compare(),
> >       const allocator_type& __a = allocator_type())
> >
> >   map(initializer_list<value_type> __l, const allocator_type& __a)
> >
> > This patch just removes these problematic container CTAD examples.
> 
> Do all the problematic cases have a corresponding case that doesn't
> use {} but uses an actual type?
> 
> If not, we might want to add such cases, to ensure we're still
> covering all the cases that really *should* work.

Ah, it looks like most tests have one such corresponding case, but since
the {} can potentially be an allocator or a function, for maximum
coverage we should have two corresponding cases.  So the revised patch
below instead replaces each problematic CTAD example with the other
untested case.

Interestingly two of these new CTAD examples for std::set and std::multiset
end up triggering an unrelated CTAD bug PR101174 on trunk, so the patch
comments out these adjusted examples for now.

-- >8 --

	PR c++/86439
	PR c++/101174

gcc/cp/ChangeLog:

	* call.c (print_error_for_call_failure): Constify 'args' parameter.
	(perform_dguide_overload_resolution): Define.
	* cp-tree.h: (perform_dguide_overload_resolution): Declare.
	* pt.c (do_class_deduction): Use perform_dguide_overload_resolution
	instead of build_new_function_call.  Don't use tf_decltype or
	set cp_unevaluated_operand.  Remove unnecessary NULL_TREE tests.

libstdc++-v3/ChangeLog:

	* testsuite/23_containers/map/cons/deduction.cc: Replace ambiguous
	CTAD examples.
	* testsuite/23_containers/multimap/cons/deduction.cc: Likewise.
	* testsuite/23_containers/multiset/cons/deduction.cc: Likewise.
	Mention one of the replaced examples is broken due to PR101174.
	* testsuite/23_containers/set/cons/deduction.cc: Likewise.
	* testsuite/23_containers/unordered_map/cons/deduction.cc: Replace
	ambiguous CTAD examples.
	* testsuite/23_containers/unordered_multimap/cons/deduction.cc:
	Likewise.
	* testsuite/23_containers/unordered_multiset/cons/deduction.cc:
	Likewise.
	* testsuite/23_containers/unordered_set/cons/deduction.cc: Likewise.

gcc/testsuite/ChangeLog:

	* g++.dg/cpp1z/class-deduction88.C: New test.
	* g++.dg/cpp1z/class-deduction89.C: New test.
	* g++.dg/cpp1z/class-deduction90.C: New test.
---
 gcc/cp/call.c                                 | 36 +++++++++++++++-
 gcc/cp/cp-tree.h                              |  2 +
 gcc/cp/pt.c                                   | 41 +++++++------------
 .../g++.dg/cpp1z/class-deduction88.C          | 18 ++++++++
 .../g++.dg/cpp1z/class-deduction89.C          | 15 +++++++
 .../g++.dg/cpp1z/class-deduction90.C          | 16 ++++++++
 .../23_containers/map/cons/deduction.cc       |  8 ++--
 .../23_containers/multimap/cons/deduction.cc  |  8 ++--
 .../23_containers/multiset/cons/deduction.cc  |  8 ++--
 .../23_containers/set/cons/deduction.cc       |  8 ++--
 .../unordered_map/cons/deduction.cc           | 17 ++++++--
 .../unordered_multimap/cons/deduction.cc      | 17 ++++++--
 .../unordered_multiset/cons/deduction.cc      | 14 ++++++-
 .../unordered_set/cons/deduction.cc           | 14 ++++++-
 14 files changed, 170 insertions(+), 52 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp1z/class-deduction88.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1z/class-deduction89.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1z/class-deduction90.C

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 9f03534c20c..aafc7acca24 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -4629,7 +4629,7 @@ perform_overload_resolution (tree fn,
    functions.  */
 
 static void
-print_error_for_call_failure (tree fn, vec<tree, va_gc> *args,
+print_error_for_call_failure (tree fn, const vec<tree, va_gc> *args,
 			      struct z_candidate *candidates)
 {
   tree targs = NULL_TREE;
@@ -4654,6 +4654,40 @@ print_error_for_call_failure (tree fn, vec<tree, va_gc> *args,
     print_z_candidates (loc, candidates);
 }
 
+/* Perform overload resolution on the set of deduction guides DGUIDES
+   using ARGS.  Returns the selected deduction guide, or error_mark_node
+   if overload resolution fails.  */
+
+tree
+perform_dguide_overload_resolution (tree dguides, const vec<tree, va_gc> *args,
+				    tsubst_flags_t complain)
+{
+  z_candidate *candidates;
+  bool any_viable_p;
+  tree result;
+
+  gcc_assert (deduction_guide_p (OVL_FIRST (dguides)));
+
+  /* Get the high-water mark for the CONVERSION_OBSTACK.  */
+  void *p = conversion_obstack_alloc (0);
+
+  z_candidate *cand = perform_overload_resolution (dguides, args, &candidates,
+						   &any_viable_p, complain);
+  if (!cand)
+    {
+      if (complain & tf_error)
+	print_error_for_call_failure (dguides, args, candidates);
+      result = error_mark_node;
+    }
+  else
+    result = cand->fn;
+
+  /* Free all the conversions we allocated.  */
+  obstack_free (&conversion_obstack, p);
+
+  return result;
+}
+
 /* Return an expression for a call to FN (a namespace-scope function,
    or a static member function) with the ARGS.  This may change
    ARGS.  */
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 36f99ccf189..6f713719589 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -6437,6 +6437,8 @@ extern void complain_about_bad_argument	(location_t arg_loc,
 						 tree from_type, tree to_type,
 						 tree fndecl, int parmnum);
 extern void maybe_inform_about_fndecl_for_bogus_argument_init (tree, int);
+extern tree perform_dguide_overload_resolution	(tree, const vec<tree, va_gc> *,
+						 tsubst_flags_t);
 
 
 /* A class for recording information about access failures (e.g. private
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 15947b2c812..732fb405adf 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -29382,7 +29382,7 @@ do_class_deduction (tree ptype, tree tmpl, tree init,
     if (tree guide = maybe_aggr_guide (tmpl, init, args))
       cands = lookup_add (guide, cands);
 
-  tree call = error_mark_node;
+  tree fndecl = error_mark_node;
 
   /* If this is list-initialization and the class has a list constructor, first
      try deducing from the list as a single argument, as [over.match.list].  */
@@ -29396,11 +29396,9 @@ do_class_deduction (tree ptype, tree tmpl, tree init,
       }
   if (list_cands)
     {
-      ++cp_unevaluated_operand;
-      call = build_new_function_call (list_cands, &args, tf_decltype);
-      --cp_unevaluated_operand;
+      fndecl = perform_dguide_overload_resolution (list_cands, args, tf_none);
 
-      if (call == error_mark_node)
+      if (fndecl == error_mark_node)
 	{
 	  /* That didn't work, now try treating the list as a sequence of
 	     arguments.  */
@@ -29416,31 +29414,22 @@ do_class_deduction (tree ptype, tree tmpl, tree init,
 	     "user-declared constructors", type);
       return error_mark_node;
     }
-  else if (!cands && call == error_mark_node)
+  else if (!cands && fndecl == error_mark_node)
     {
       error ("cannot deduce template arguments of %qT, as it has no viable "
 	     "deduction guides", type);
       return error_mark_node;
     }
 
-  if (call == error_mark_node)
-    {
-      ++cp_unevaluated_operand;
-      call = build_new_function_call (cands, &args, tf_decltype);
-      --cp_unevaluated_operand;
-    }
+  if (fndecl == error_mark_node)
+    fndecl = perform_dguide_overload_resolution (cands, args, tf_none);
 
-  if (call == error_mark_node)
+  if (fndecl == error_mark_node)
     {
       if (complain & tf_warning_or_error)
 	{
 	  error ("class template argument deduction failed:");
-
-	  ++cp_unevaluated_operand;
-	  call = build_new_function_call (cands, &args,
-					  complain | tf_decltype);
-	  --cp_unevaluated_operand;
-
+	  perform_dguide_overload_resolution (cands, args, complain);
 	  if (elided)
 	    inform (input_location, "explicit deduction guides not considered "
 		    "for copy-initialization");
@@ -29451,8 +29440,7 @@ do_class_deduction (tree ptype, tree tmpl, tree init,
      constructor is chosen, the initialization is ill-formed.  */
   else if (flags & LOOKUP_ONLYCONVERTING)
     {
-      tree fndecl = cp_get_callee_fndecl_nofold (call);
-      if (fndecl && DECL_NONCONVERTING_P (fndecl))
+      if (DECL_NONCONVERTING_P (fndecl))
 	{
 	  if (complain & tf_warning_or_error)
 	    {
@@ -29470,12 +29458,10 @@ do_class_deduction (tree ptype, tree tmpl, tree init,
 
   /* If CTAD succeeded but the type doesn't have any explicit deduction
      guides, this deduction might not be what the user intended.  */
-  if (call != error_mark_node && !any_dguides_p)
+  if (fndecl != error_mark_node && !any_dguides_p)
     {
-      tree fndecl = cp_get_callee_fndecl_nofold (call);
-      if (fndecl != NULL_TREE
-	  && (!DECL_IN_SYSTEM_HEADER (fndecl)
-	      || global_dc->dc_warn_system_headers)
+      if ((!DECL_IN_SYSTEM_HEADER (fndecl)
+	   || global_dc->dc_warn_system_headers)
 	  && warning (OPT_Wctad_maybe_unsupported,
 		      "%qT may not intend to support class template argument "
 		      "deduction", type))
@@ -29483,7 +29469,8 @@ do_class_deduction (tree ptype, tree tmpl, tree init,
 		"warning");
     }
 
-  return cp_build_qualified_type (TREE_TYPE (call), cp_type_quals (ptype));
+  return cp_build_qualified_type (TREE_TYPE (TREE_TYPE (fndecl)),
+				  cp_type_quals (ptype));
 }
 
 /* Replace occurrences of 'auto' in TYPE with the appropriate type deduced
diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction88.C b/gcc/testsuite/g++.dg/cpp1z/class-deduction88.C
new file mode 100644
index 00000000000..be38fed2901
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction88.C
@@ -0,0 +1,18 @@
+// PR c++/86439
+// { dg-do compile { target c++17 } }
+
+struct NC {
+  NC() = default;
+  NC(NC const&) = delete;
+  NC& operator=(NC const&) = delete;
+};
+
+template <int>
+struct C {
+  C(NC const&);
+};
+
+C(NC) -> C<0>;
+
+NC nc;
+C c(nc);
diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction89.C b/gcc/testsuite/g++.dg/cpp1z/class-deduction89.C
new file mode 100644
index 00000000000..dd898573022
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction89.C
@@ -0,0 +1,15 @@
+// PR c++/86439
+// { dg-do compile { target c++17 } }
+
+struct B { };
+struct C { };
+
+template<class T>
+struct A {
+  A(T, B);
+};
+
+template<class T>
+A(T, C) -> A<T>;
+
+A a(0, {});
diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction90.C b/gcc/testsuite/g++.dg/cpp1z/class-deduction90.C
new file mode 100644
index 00000000000..8b93193c7b0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction90.C
@@ -0,0 +1,16 @@
+// PR c++/86439
+// { dg-do compile { target c++17 } }
+
+struct less { };
+struct allocator { };
+
+template<class T, class U = less, class V = allocator>
+struct A {
+  A(T, U);
+  A(T, V);
+};
+
+template<class T, class U = less>
+A(T, U) -> A<T>;
+
+A a(0, {}); // { dg-error "ambiguous" }
diff --git a/libstdc++-v3/testsuite/23_containers/map/cons/deduction.cc b/libstdc++-v3/testsuite/23_containers/map/cons/deduction.cc
index e9628c4ac32..e72033c38a6 100644
--- a/libstdc++-v3/testsuite/23_containers/map/cons/deduction.cc
+++ b/libstdc++-v3/testsuite/23_containers/map/cons/deduction.cc
@@ -40,7 +40,7 @@ static_assert(std::is_same_v<
 */
 
 static_assert(std::is_same_v<
-	      decltype(std::map{{std::pair{1, 2.0}, {2, 3.0}, {3, 4.0}}, {}}),
+	      decltype(std::map{{std::pair{1, 2.0}, {2, 3.0}, {3, 4.0}}, std::less<int>{}}),
 	      std::map<int, double>>);
 
 /* This is not deducible, ambiguous candidates:
@@ -92,7 +92,7 @@ void f()
 
   static_assert(std::is_same_v<
 		decltype(std::map(x.begin(), x.end(),
-				  {})),
+				  std::less<int>{})),
 		std::map<int, double>>);
 
   static_assert(std::is_same_v<
@@ -145,7 +145,7 @@ void g()
 
   static_assert(std::is_same_v<
 		decltype(std::map(x.begin(), x.end(),
-				  {})),
+				  std::less<int>{})),
 		std::map<int, double>>);
 
   static_assert(std::is_same_v<
@@ -195,7 +195,7 @@ void h()
 
   static_assert(std::is_same_v<
 		decltype(std::map(x.begin(), x.end(),
-				  {})),
+				  std::less<int>{})),
 		std::map<int, double>>);
 
   static_assert(std::is_same_v<
diff --git a/libstdc++-v3/testsuite/23_containers/multimap/cons/deduction.cc b/libstdc++-v3/testsuite/23_containers/multimap/cons/deduction.cc
index 791cc963479..ffc7502d60c 100644
--- a/libstdc++-v3/testsuite/23_containers/multimap/cons/deduction.cc
+++ b/libstdc++-v3/testsuite/23_containers/multimap/cons/deduction.cc
@@ -42,7 +42,7 @@ static_assert(std::is_same_v<
 
 static_assert(std::is_same_v<
 	      decltype(std::multimap{{std::pair{1, 2.0}, {2, 3.0}, {3, 4.0}},
-		    {}}),
+		    std::less<int>{}}),
 	      std::multimap<int, double>>);
 
 static_assert(std::is_same_v<
@@ -77,7 +77,7 @@ void f()
 
   static_assert(std::is_same_v<
 		decltype(std::multimap(x.begin(), x.end(),
-				       {})),
+				       std::less<int>{})),
 		std::multimap<int, double>>);
 
   static_assert(std::is_same_v<
@@ -119,7 +119,7 @@ void g()
 
   static_assert(std::is_same_v<
 		decltype(std::multimap(x.begin(), x.end(),
-				       {})),
+				       std::less<int>{})),
 		std::multimap<int, double>>);
 
   static_assert(std::is_same_v<
@@ -158,7 +158,7 @@ void h()
 
   static_assert(std::is_same_v<
 		decltype(std::multimap(x.begin(), x.end(),
-				       {})),
+				       std::less<int>{})),
 		std::multimap<int, double>>);
 
   static_assert(std::is_same_v<
diff --git a/libstdc++-v3/testsuite/23_containers/multiset/cons/deduction.cc b/libstdc++-v3/testsuite/23_containers/multiset/cons/deduction.cc
index ad12755ccc6..a4ccc6fa467 100644
--- a/libstdc++-v3/testsuite/23_containers/multiset/cons/deduction.cc
+++ b/libstdc++-v3/testsuite/23_containers/multiset/cons/deduction.cc
@@ -19,9 +19,11 @@ static_assert(std::is_same_v<
 	      decltype(std::multiset{{1, 2, 3}, std::less<int>{}, {}}),
 	      std::multiset<int>>);
 
+/* FIXME: GCC 12 rejects this due to PR c++/101174
 static_assert(std::is_same_v<
-	      decltype(std::multiset{{1, 2, 3}, {}}),
+	      decltype(std::multiset{{1, 2, 3}, std::less<int>{}}),
 	      std::multiset<int>>);
+*/
 
 static_assert(std::is_same_v<
 	      decltype(std::multiset{{1, 2, 3}, SimpleAllocator<int>{}}),
@@ -52,7 +54,7 @@ void f()
 
   static_assert(std::is_same_v<
 		decltype(std::multiset(x.begin(), x.end(),
-				  {})),
+				  std::less<int>{})),
 		std::multiset<int>>);
 
   static_assert(std::is_same_v<
@@ -103,7 +105,7 @@ void g()
 
   static_assert(std::is_same_v<
 		decltype(std::multiset(x.begin(), x.end(),
-				  {})),
+				  std::less<int>{})),
 		std::multiset<int>>);
 
   static_assert(std::is_same_v<
diff --git a/libstdc++-v3/testsuite/23_containers/set/cons/deduction.cc b/libstdc++-v3/testsuite/23_containers/set/cons/deduction.cc
index 89a2c43b937..0ae4c2a5c5f 100644
--- a/libstdc++-v3/testsuite/23_containers/set/cons/deduction.cc
+++ b/libstdc++-v3/testsuite/23_containers/set/cons/deduction.cc
@@ -20,10 +20,12 @@ static_assert(std::is_same_v<
 		    std::less<int>{}, {}}),
 	      std::set<int>>);
 
+/* FIXME: GCC 12 rejects this due to PR c++/101174
 static_assert(std::is_same_v<
 	      decltype(std::set{{1, 2, 3},
-		    {}}),
+		    std::less<int>{}}),
 	      std::set<int>>);
+*/
 
 static_assert(std::is_same_v<
 	      decltype(std::set{{1, 2, 3},
@@ -58,7 +60,7 @@ void f()
 
   static_assert(std::is_same_v<
 		decltype(std::set(x.begin(), x.end(),
-				  {})),
+				  std::less<int>{})),
 		std::set<int>>);
 
   static_assert(std::is_same_v<
@@ -104,7 +106,7 @@ void g()
 
   static_assert(std::is_same_v<
 		decltype(std::set(x.begin(), x.end(),
-				  {})),
+				  std::less<int>{})),
 		std::set<int>>);
 
   static_assert(std::is_same_v<
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_map/cons/deduction.cc b/libstdc++-v3/testsuite/23_containers/unordered_map/cons/deduction.cc
index d8489b23f8a..0785447a81b 100644
--- a/libstdc++-v3/testsuite/23_containers/unordered_map/cons/deduction.cc
+++ b/libstdc++-v3/testsuite/23_containers/unordered_map/cons/deduction.cc
@@ -24,7 +24,13 @@ static_assert(std::is_same_v<
 static_assert(std::is_same_v<
 	      decltype(std::unordered_map{{std::pair{1, 2.0},
 		      {2, 3.0}, {3, 4.0}},
-		    {}, std::hash<int>{}, {}}),
+		    {}, std::hash<int>{}, std::equal_to<int>{}}),
+	      std::unordered_map<int, double>>);
+
+static_assert(std::is_same_v<
+	      decltype(std::unordered_map{{std::pair{1, 2.0},
+		      {2, 3.0}, {3, 4.0}},
+		    {}, std::hash<int>{}, std::allocator<std::pair<const int, double>>{}}),
 	      std::unordered_map<int, double>>);
 
 static_assert(std::is_same_v<
@@ -59,9 +65,14 @@ void f()
 
   static_assert(std::is_same_v<
 		decltype(std::unordered_map{x.begin(), x.end(),
-		      {}, std::hash<int>{}, {}}),
+		      {}, std::hash<int>{}, std::equal_to<int>{}}),
 		std::unordered_map<int, double>>);
-  
+
+  static_assert(std::is_same_v<
+		decltype(std::unordered_map{x.begin(), x.end(),
+		      {}, std::hash<int>{}, std::allocator<std::pair<const int, double>>{}}),
+		std::unordered_map<int, double>>);
+
   static_assert(std::is_same_v<
 		decltype(std::unordered_map(x.begin(), x.end(),
 		      {})),
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multimap/cons/deduction.cc b/libstdc++-v3/testsuite/23_containers/unordered_multimap/cons/deduction.cc
index 13f54d43451..d8a6f5136c9 100644
--- a/libstdc++-v3/testsuite/23_containers/unordered_multimap/cons/deduction.cc
+++ b/libstdc++-v3/testsuite/23_containers/unordered_multimap/cons/deduction.cc
@@ -18,7 +18,13 @@ static_assert(std::is_same_v<
 static_assert(std::is_same_v<
 	      decltype(std::unordered_multimap{{std::pair{1, 2.0},
 		      {2, 3.0}, {3, 4.0}},
-		    {}, std::hash<int>{}, {}}),
+		    {}, std::hash<int>{}, std::equal_to<int>{}}),
+	      std::unordered_multimap<int, double>>);
+
+static_assert(std::is_same_v<
+	      decltype(std::unordered_multimap{{std::pair{1, 2.0},
+		      {2, 3.0}, {3, 4.0}},
+		    {}, std::hash<int>{}, std::allocator<std::pair<const int, double>>{}}),
 	      std::unordered_multimap<int, double>>);
 
 static_assert(std::is_same_v<
@@ -68,9 +74,14 @@ void f()
 
   static_assert(std::is_same_v<
 		decltype(std::unordered_multimap{x.begin(), x.end(),
-		      {}, std::hash<int>{}, {}}),
+		      {}, std::hash<int>{}, std::equal_to<int>{}}),
 		std::unordered_multimap<int, double>>);
-  
+
+  static_assert(std::is_same_v<
+		decltype(std::unordered_multimap{x.begin(), x.end(),
+		      {}, std::hash<int>{}, std::allocator<std::pair<const int, double>>{}}),
+		std::unordered_multimap<int, double>>);
+
   static_assert(std::is_same_v<
 		decltype(std::unordered_multimap(x.begin(), x.end(),
 				  {})),
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multiset/cons/deduction.cc b/libstdc++-v3/testsuite/23_containers/unordered_multiset/cons/deduction.cc
index 1850237e44c..25c2715ea26 100644
--- a/libstdc++-v3/testsuite/23_containers/unordered_multiset/cons/deduction.cc
+++ b/libstdc++-v3/testsuite/23_containers/unordered_multiset/cons/deduction.cc
@@ -11,7 +11,12 @@ static_assert(std::is_same_v<
 
 static_assert(std::is_same_v<
 	      decltype(std::unordered_multiset{{1, 2, 3},
-		    0, std::hash<int>{}, {}}),
+		    0, std::hash<int>{}, std::equal_to<int>{}}),
+	      std::unordered_multiset<int>>);
+
+static_assert(std::is_same_v<
+	      decltype(std::unordered_multiset{{1, 2, 3},
+		    0, std::hash<int>{}, std::allocator<int>{}}),
 	      std::unordered_multiset<int>>);
 
 static_assert(std::is_same_v<
@@ -78,7 +83,12 @@ void f()
 
   static_assert(std::is_same_v<
 		decltype(std::unordered_multiset{x.begin(), x.end(),
-		      {}, std::hash<int>{}, {}}),
+		      {}, std::hash<int>{}, std::equal_to<int>{}}),
+		std::unordered_multiset<int>>);
+
+  static_assert(std::is_same_v<
+		decltype(std::unordered_multiset{x.begin(), x.end(),
+		      {}, std::hash<int>{}, std::allocator<int>{}}),
 		std::unordered_multiset<int>>);
 
   static_assert(std::is_same_v<
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_set/cons/deduction.cc b/libstdc++-v3/testsuite/23_containers/unordered_set/cons/deduction.cc
index a745dce0fba..b8c45d2993d 100644
--- a/libstdc++-v3/testsuite/23_containers/unordered_set/cons/deduction.cc
+++ b/libstdc++-v3/testsuite/23_containers/unordered_set/cons/deduction.cc
@@ -11,7 +11,12 @@ static_assert(std::is_same_v<
 
 static_assert(std::is_same_v<
 	      decltype(std::unordered_set{{1, 2, 3},
-		    0, std::hash<int>{}, {}}),
+		    0, std::hash<int>{}, std::equal_to<int>{}}),
+	      std::unordered_set<int>>);
+
+static_assert(std::is_same_v<
+	      decltype(std::unordered_set{{1, 2, 3},
+		    0, std::hash<int>{}, std::allocator<int>{}}),
 	      std::unordered_set<int>>);
 
 static_assert(std::is_same_v<
@@ -73,7 +78,12 @@ void f()
 
   static_assert(std::is_same_v<
 		decltype(std::unordered_set{x.begin(), x.end(),
-		      {}, std::hash<int>{}, {}}),
+		      {}, std::hash<int>{}, std::equal_to<int>{}}),
+		std::unordered_set<int>>);
+
+  static_assert(std::is_same_v<
+		decltype(std::unordered_set{x.begin(), x.end(),
+		      {}, std::hash<int>{}, std::allocator<int>{}}),
 		std::unordered_set<int>>);
 
   static_assert(std::is_same_v<
-- 
2.32.0.93.g670b81a890



More information about the Gcc-patches mailing list