diff mbox

C++ PATCH to implement P0702R1, list-deduction of vector

Message ID CADzB+2=zqY=ETudPScCq4s-O3_9ZuTX9JvS9c2+n1yDNmEYRuQ@mail.gmail.com
State New
Headers show

Commit Message

Jason Merrill July 26, 2017, 5:38 p.m. UTC
At the Toronto meeting we adjusted the semantics of class template
argument deduction for a class such as std::vector that has an
initializer-list constructor: previously, we would get

vector v1 { 42 }; // vector<int>
vector v2 { v1 }; // vector<vector<int>>

but now v2 is also deduced to vector<int>.

Tested x86_64-pc-linux-gnu, applying to trunk.
commit d2725cd7aad7bec11c2d2ced6f5a02de83fe0427
Author: Jason Merrill <jason@redhat.com>
Date:   Wed Jul 12 13:47:16 2017 -0400

            P0702R1 - List deduction of vector.
    
            * pt.c (do_class_deduction): Special-case deduction from a single
            element of related type.
diff mbox

Patch

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index bb32353..173ec3f 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -25331,6 +25331,24 @@  do_class_deduction (tree ptype, tree tmpl, tree init, int flags,
   else if (BRACE_ENCLOSED_INITIALIZER_P (init))
     {
       try_list_ctor = TYPE_HAS_LIST_CTOR (type);
+      if (try_list_ctor && CONSTRUCTOR_NELTS (init) == 1)
+	{
+	  /* As an exception, the first phase in 16.3.1.7 (considering the
+	     initializer list as a single argument) is omitted if the
+	     initializer list consists of a single expression of type cv U,
+	     where U is a specialization of C or a class derived from a
+	     specialization of C.  */
+	  tree elt = CONSTRUCTOR_ELT (init, 0)->value;
+	  tree etype = TREE_TYPE (elt);
+
+	  tree tparms = INNERMOST_TEMPLATE_PARMS (DECL_TEMPLATE_PARMS (tmpl));
+	  tree targs = make_tree_vec (TREE_VEC_LENGTH (tparms));
+	  int err = unify (tparms, targs, type, etype,
+			   UNIFY_ALLOW_DERIVED, /*explain*/false);
+	  if (err == 0)
+	    try_list_ctor = false;
+	  ggc_free (targs);
+	}
       if (try_list_ctor || is_std_init_list (type))
 	args = make_tree_vector_single (init);
       else
diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction42.C b/gcc/testsuite/g++.dg/cpp1z/class-deduction42.C
new file mode 100644
index 0000000..8217fd4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction42.C
@@ -0,0 +1,19 @@ 
+// { dg-options -std=c++1z }
+
+#include <initializer_list>
+
+template <class,class> struct same;
+template <class T> struct same<T,T> { };
+
+template <class T>
+struct A
+{
+  A(const A&);
+  A(std::initializer_list<T>);
+};
+
+A a { 1 };
+A b { a };
+
+same<decltype (a), decltype (b)> s;
+