This snippet doesn't work: #include <vector> #include <algorithm> #include <iostream> using namespace std; template <class zomg> class T { vector<int> v{2,6,4,1,7,1}; // #1, fails static int comp(int x, int y) {return x < y;} public: void sort_me() {sort(v.begin(), v.end(), comp);} void print_me() {for (auto x : v) cout << x << endl;} }; int main() { T<int> t; t.sort_me(); t.print_me(); } It works if T is not a class template. It also works if the line marked #1 is written as vector<int> v = {2,6,4,1,7,1}; both in a class template and in a normal class. Fails the same way with 4.7.2, 4.8 and 4.9 trunk. Full diagnostics: plaatti.cpp: In constructor ‘constexpr T<int>::T()’: plaatti.cpp:8:7: error: no matching function for call to ‘std::vector<int>::vector(<brace-enclosed initializer list>)’ class T { ^ plaatti.cpp:8:7: note: candidates are: In file included from /usr/local/include/c++/4.9.0/vector:64:0, from plaatti.cpp:1: /usr/local/include/c++/4.9.0/bits/stl_vector.h:386:9: note: template<class _InputIterator, class> std::vector<_Tp, _Alloc>::vector(_InputIterator, _InputIterator, const allocator_type&) vector(_InputIterator __first, _InputIterator __last, ^ /usr/local/include/c++/4.9.0/bits/stl_vector.h:386:9: note: template argument deduction/substitution failed: plaatti.cpp:8:7: note: cannot convert ‘4’ (type ‘int’) to type ‘const allocator_type& {aka const std::allocator<int>&}’ class T { ^ In file included from /usr/local/include/c++/4.9.0/vector:64:0, from plaatti.cpp:1: /usr/local/include/c++/4.9.0/bits/stl_vector.h:358:7: note: std::vector<_Tp, _Alloc>::vector(std::initializer_list<_Tp>, const allocator_type&) [with _Tp = int; _Alloc = std::allocator<int>; std::vector<_Tp, _Alloc>::allocator_type = std::allocator<int>] vector(initializer_list<value_type> __l, ^ /usr/local/include/c++/4.9.0/bits/stl_vector.h:358:7: note: candidate expects 2 arguments, 6 provided In file included from /usr/local/include/c++/4.9.0/vector:64:0, from plaatti.cpp:1: /usr/local/include/c++/4.9.0/bits/stl_vector.h:334:7: note: std::vector<_Tp, _Alloc>::vector(std::vector<_Tp, _Alloc>&&, const allocator_type&) [with _Tp = int; _Alloc = std::allocator<int>; std::vector<_Tp, _Alloc>::allocator_type = std::allocator<int>] vector(vector&& __rv, const allocator_type& __m) ^ /usr/local/include/c++/4.9.0/bits/stl_vector.h:334:7: note: candidate expects 2 arguments, 6 provided /usr/local/include/c++/4.9.0/bits/stl_vector.h:325:7: note: std::vector<_Tp, _Alloc>::vector(const std::vector<_Tp, _Alloc>&, const allocator_type&) [with _Tp = int; _Alloc = std::allocator<int>; std::vector<_Tp, _Alloc>::allocator_type = std::allocator<int>] vector(const vector& __x, const allocator_type& __a) ^ /usr/local/include/c++/4.9.0/bits/stl_vector.h:325:7: note: candidate expects 2 arguments, 6 provided /usr/local/include/c++/4.9.0/bits/stl_vector.h:321:7: note: std::vector<_Tp, _Alloc>::vector(std::vector<_Tp, _Alloc>&&) [with _Tp = int; _Alloc = std::allocator<int>] vector(vector&& __x) noexcept ^ /usr/local/include/c++/4.9.0/bits/stl_vector.h:321:7: note: candidate expects 1 argument, 6 provided In file included from /usr/local/include/c++/4.9.0/vector:64:0, from plaatti.cpp:1: /usr/local/include/c++/4.9.0/bits/stl_vector.h:304:7: note: std::vector<_Tp, _Alloc>::vector(const std::vector<_Tp, _Alloc>&) [with _Tp = int; _Alloc = std::allocator<int>] vector(const vector& __x) ^ /usr/local/include/c++/4.9.0/bits/stl_vector.h:304:7: note: candidate expects 1 argument, 6 provided In file included from /usr/local/include/c++/4.9.0/vector:64:0, from plaatti.cpp:1: /usr/local/include/c++/4.9.0/bits/stl_vector.h:275:7: note: std::vector<_Tp, _Alloc>::vector(std::vector<_Tp, _Alloc>::size_type, const value_type&, const allocator_type&) [with _Tp = int; _Alloc = std::allocator<int>; std::vector<_Tp, _Alloc>::size_type = long unsigned int; std::vector<_Tp, _Alloc>::value_type = int; std::vector<_Tp, _Alloc>::allocator_type = std::allocator<int>] vector(size_type __n, const value_type& __value, ^ /usr/local/include/c++/4.9.0/bits/stl_vector.h:275:7: note: candidate expects 3 arguments, 6 provided In file included from /usr/local/include/c++/4.9.0/vector:64:0, from plaatti.cpp:1: /usr/local/include/c++/4.9.0/bits/stl_vector.h:263:7: note: std::vector<_Tp, _Alloc>::vector(std::vector<_Tp, _Alloc>::size_type, const allocator_type&) [with _Tp = int; _Alloc = std::allocator<int>; std::vector<_Tp, _Alloc>::size_type = long unsigned int; std::vector<_Tp, _Alloc>::allocator_type = std::allocator<int>] vector(size_type __n, const allocator_type& __a = allocator_type()) ^ /usr/local/include/c++/4.9.0/bits/stl_vector.h:263:7: note: candidate expects 2 arguments, 6 provided In file included from /usr/local/include/c++/4.9.0/vector:64:0, from plaatti.cpp:1: /usr/local/include/c++/4.9.0/bits/stl_vector.h:250:7: note: std::vector<_Tp, _Alloc>::vector(const allocator_type&) [with _Tp = int; _Alloc = std::allocator<int>; std::vector<_Tp, _Alloc>::allocator_type = std::allocator<int>] vector(const allocator_type& __a = allocator_type()) _GLIBCXX_NOEXCEPT ^ /usr/local/include/c++/4.9.0/bits/stl_vector.h:250:7: note: candidate expects 1 argument, 6 provided plaatti.cpp: In function ‘int main()’: plaatti.cpp:20:10: note: synthesized method ‘constexpr T<int>::T()’ first required here T<int> t; ^
We badly need a reduced testcase.
This snippet #include <vector> struct X {X(int) {}}; template <class zomg> class T { std::vector<int> x{0}; }; int main() { T<int> t; } gives the following: plaatti-reduced.cpp: In constructor ‘constexpr T<int>::T()’: plaatti-reduced.cpp:6:7: error: converting to ‘std::vector<int>’ from initializer list would use explicit constructor ‘std::vector<_Tp, _Alloc>::vector(std::vector<_Tp, _Alloc>::size_type, const allocator_type&) [with _Tp = int; _Alloc = std::allocator<int>; std::vector<_Tp, _Alloc>::size_type = long unsigned int; std::vector<_Tp, _Alloc>::allocator_type = std::allocator<int>]’ class T { ^ plaatti-reduced.cpp: In function ‘int main()’: plaatti-reduced.cpp:13:10: note: synthesized method ‘constexpr T<int>::T()’ first required here T<int> t; ^ A non-template is still fine, and a copy-initialized brace-NSDMI is still fine.
And, the struct X is not significant, but I tested with just a simple type that can be brace-initialized, and that didn't trigger the error. I haven't yet narrowed it down to initializer_list or anything like that, vector seems to be a surefire way to trigger it.
Thanks Ville. I'm thinking something not including the whole <vector>. I bet 20-30 lines are enough.
I will try a couple of tricks to try and get rid of vector. I don't think it's a library bug, perhaps additional constructor overloads can trigger it. But that'll have to wait until tomorrow. :)
Just one thing: I find it confusing that the diagnostics say "synthesized method ‘constexpr T<int>::T()" (note the constexpr), there's not a snowball's chance in hell that that constructor is ever constexpr, since we _do_ have a vector member here.
I see. Let's have first something of manageable size ;) Thanks again!
Slightly reduced, I guess... #include <initializer_list> template <class T> struct X {X(std::initializer_list<int>) {}}; template <class zomg> class T { X<T> x{1}; }; int main() { T<int> t; } This gives plaatti-reduced2.cpp: In constructor ‘constexpr T<int>::T()’: plaatti-reduced2.cpp:7:7: error: no matching function for call to ‘X<T<int> >::X(<brace-enclosed initializer list>)’ class T { ^ plaatti-reduced2.cpp:7:7: note: candidates are: plaatti-reduced2.cpp:4:11: note: X<T>::X(std::initializer_list<int>) [with T = T<int>] struct X {X(std::initializer_list<int>) {}}; ^ plaatti-reduced2.cpp:4:8: note: constexpr X<T<int> >::X(const X<T<int> >&) struct X {X(std::initializer_list<int>) {}}; ^ plaatti-reduced2.cpp:4:8: note: no known conversion for argument 1 from ‘int’ to ‘const X<T<int> >&’ plaatti-reduced2.cpp:4:8: note: constexpr X<T<int> >::X(X<T<int> >&&) plaatti-reduced2.cpp:4:8: note: no known conversion for argument 1 from ‘int’ to ‘X<T<int> >&&’ plaatti-reduced2.cpp: In function ‘int main()’: plaatti-reduced2.cpp:14:10: note: synthesized method ‘constexpr T<int>::T()’ first required here T<int> t; ^
Thanks!
Ville, I believe PR58930 is essentially the same issue with a slightly smaller testcase. What do you think?
(In reply to Paolo Carlini from comment #10) Looks somewhat similar, but not identical. In this particular bug it doesn't seem to be a case of explicitness being the problem.
It is in Comment #2, though. In fact, I *only* noticed that one when I asked ;) Anyway, I was looking a bit into the other bug and interestingly a rather rough draft I have got appears to fix all these issues at once without causing regressions: Index: init.c =================================================================== --- init.c (revision 210459) +++ init.c (working copy) @@ -644,7 +644,8 @@ || (TREE_CODE (init) == TREE_LIST && DIRECT_LIST_INIT_P (TREE_VALUE (init)))) && (CP_AGGREGATE_TYPE_P (type) - || is_std_init_list (type))))) + || is_std_init_list (type))) + || DIRECT_LIST_INIT_P (init))) { /* With references and list-initialization, we need to deal with extending temporary lifetimes. 12.2p5: "A temporary bound to a
(In reply to Paolo Carlini from comment #12) Ah, indeed, comment 2 has an explicit diagnostic as well. The patch looks reasonable (to my taste the condition doesn't, but that's another matter), so I recommend sending it to the mighty maintainer for review.
Author: paolo Date: Tue May 20 19:20:59 2014 New Revision: 210653 URL: http://gcc.gnu.org/viewcvs?rev=210653&root=gcc&view=rev Log: /cp 2014-05-20 Paolo Carlini <paolo.carlini@oracle.com> PR c++/58753 PR c++/58930 PR c++/58704 * typeck2.c (digest_nsdmi_init): New. * parser.c (cp_parser_late_parse_one_default_arg): Use it. * init.c (get_nsdmi): Likewise. * cp-tree.h (digest_nsdmi_init): Declare. /testsuite 2014-05-20 Paolo Carlini <paolo.carlini@oracle.com> PR c++/58753 PR c++/58930 PR c++/58704 * g++.dg/cpp0x/nsdmi-template11.C: New. * g++.dg/cpp0x/nsdmi-template12.C: Likewise. * g++.dg/cpp0x/nsdmi-template13.C: Likewise. Added: trunk/gcc/testsuite/g++.dg/cpp0x/nsdmi-template11.C trunk/gcc/testsuite/g++.dg/cpp0x/nsdmi-template12.C trunk/gcc/testsuite/g++.dg/cpp0x/nsdmi-template13.C Modified: trunk/gcc/cp/ChangeLog trunk/gcc/cp/cp-tree.h trunk/gcc/cp/init.c trunk/gcc/cp/parser.c trunk/gcc/cp/typeck2.c trunk/gcc/testsuite/ChangeLog
Fixed for 4.10.0.
Author: ppluzhnikov Date: Tue Jul 1 18:46:26 2014 New Revision: 212207 URL: https://gcc.gnu.org/viewcvs?rev=212207&root=gcc&view=rev Log: Backport r210653 from mainline: gcc/teststuite/ChangeLog: 2014-07-01 Paul Pluzhnikov <ppluzhnikov@google.com> PR c++/58753 PR c++/58930 PR c++/58704 Backported from mainline 2014-05-20 Paolo Carlini <paolo.carlini@oracle.com> * g++.dg/cpp0x/nsdmi-template11.C: New. * g++.dg/cpp0x/nsdmi-template12.C: Likewise. * g++.dg/cpp0x/nsdmi-template13.C: Likewise. gcc/cp/ChangeLog: 2014-07-01 Paul Pluzhnikov <ppluzhnikov@google.com> PR c++/58753 PR c++/58930 PR c++/58704 Backported from mainline 2014-05-20 Paolo Carlini <paolo.carlini@oracle.com> * typeck2.c (digest_nsdmi_init): New. * parser.c (cp_parser_late_parse_one_default_arg): Use it. * init.c (get_nsdmi): Likewise. * cp-tree.h (digest_nsdmi_init): Declare. Added: branches/gcc-4_9-branch/gcc/testsuite/g++.dg/cpp0x/nsdmi-template11.C branches/gcc-4_9-branch/gcc/testsuite/g++.dg/cpp0x/nsdmi-template12.C branches/gcc-4_9-branch/gcc/testsuite/g++.dg/cpp0x/nsdmi-template13.C Modified: branches/gcc-4_9-branch/gcc/cp/ChangeLog branches/gcc-4_9-branch/gcc/cp/cp-tree.h branches/gcc-4_9-branch/gcc/cp/init.c branches/gcc-4_9-branch/gcc/cp/parser.c branches/gcc-4_9-branch/gcc/cp/typeck2.c branches/gcc-4_9-branch/gcc/testsuite/ChangeLog
In the 4.9 branch, these new tests fails to compile (ARM & AArch64 targets). I can see these error messages: /aci-gcc-fsf/sources/gcc-fsf/gccsrc/gcc/testsuite/g++.dg/cpp0x/nsdmi-template11.C:19:8: error: redefinition of 'struct SampleModule' /aci-gcc-fsf/sources/gcc-fsf/gccsrc/gcc/testsuite/g++.dg/cpp0x/nsdmi-template11.C:4:8: error: previous definition of 'struct SampleModule' /aci-gcc-fsf/sources/gcc-fsf/gccsrc/gcc/testsuite/g++.dg/cpp0x/nsdmi-template11.C:25:8: error: redefinition of 'struct BaseHandler< <template-parameter-1-1> >' /aci-gcc-fsf/sources/gcc-fsf/gccsrc/gcc/testsuite/g++.dg/cpp0x/nsdmi-template11.C:10:8: error: previous definition of 'struct BaseHandler< <template-parameter-1-1> >' /aci-gcc-fsf/sources/gcc-fsf/gccsrc/gcc/testsuite/g++.dg/cpp0x/nsdmi-template12.C:24:8: error: redefinition of 'struct X<T>' /aci-gcc-fsf/sources/gcc-fsf/gccsrc/gcc/testsuite/g++.dg/cpp0x/nsdmi-template12.C:7:8: error: previous definition of 'struct X<T>' /aci-gcc-fsf/sources/gcc-fsf/gccsrc/gcc/testsuite/g++.dg/cpp0x/nsdmi-template12.C:27:7: error: redefinition of 'class T<zomg>' /aci-gcc-fsf/sources/gcc-fsf/gccsrc/gcc/testsuite/g++.dg/cpp0x/nsdmi-template12.C:10:7: error: previous definition of 'class T<zomg>' /aci-gcc-fsf/sources/gcc-fsf/gccsrc/gcc/testsuite/g++.dg/cpp0x/nsdmi-template12.C: In function 'int main()': /aci-gcc-fsf/sources/gcc-fsf/gccsrc/gcc/testsuite/g++.dg/cpp0x/nsdmi-template12.C:31:5: error: redefinition of 'int main()' /aci-gcc-fsf/sources/gcc-fsf/gccsrc/gcc/testsuite/g++.dg/cpp0x/nsdmi-template12.C:14:5: note: 'int main()' previously defined here /aci-gcc-fsf/sources/gcc-fsf/gccsrc/gcc/testsuite/g++.dg/cpp0x/nsdmi-template13.C:15:8: error: redefinition of 'struct A' /aci-gcc-fsf/sources/gcc-fsf/gccsrc/gcc/testsuite/g++.dg/cpp0x/nsdmi-template13.C:4:8: error: previous definition of 'struct A' /aci-gcc-fsf/sources/gcc-fsf/gccsrc/gcc/testsuite/g++.dg/cpp0x/nsdmi-template13.C:17:27: error: redefinition of 'struct B< <template-parameter-1-1> >' /aci-gcc-fsf/sources/gcc-fsf/gccsrc/gcc/testsuite/g++.dg/cpp0x/nsdmi-template13.C:6:27: error: previous definition of 'struct B< <template-parameter-1-1> >' /aci-gcc-fsf/sources/gcc-fsf/gccsrc/gcc/testsuite/g++.dg/cpp0x/nsdmi-template13.C:22:8: error: redefinition of 'B<int> b' /aci-gcc-fsf/sources/gcc-fsf/gccsrc/gcc/testsuite/g++.dg/cpp0x/nsdmi-template13.C:11:8: note: 'B<int> b' previously defined here
Actually fixed by followup commit 212208. Sorry for the noise.