https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66961
Bug ID: 66961 Summary: Error parsing multiple template arguments in member initializer via assignment operator Product: gcc Version: 5.1.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: akhripin at bostondynamics dot com Target Milestone: --- Created attachment 36026 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=36026&action=edit Copy of test code The following code fails to compile (there's five variants shown, with six workarounds that might help illuminate the problem) I've tried gcc 5.1.0, gcc 4.8.5, and gcc 4.8.3 #include <array> const size_t SIZE_3 = 3; template <class T1, class T2> struct TemplateTest {}; struct a_type; struct another_type; typedef int int_type; struct Test { enum { SIZE_1 = 1 }; static const size_t SIZE_2 = 2; #if 1 // broken : std::array<void*, SIZE_1> array1 = std::array<void*, SIZE_1>({nullptr}); std::array<void*, SIZE_2> array2 = std::array<void*, SIZE_2>({nullptr}); std::array<void*, SIZE_3> array3 = std::array<void*, SIZE_3>({nullptr}); TemplateTest<a_type, another_type> struct1 = TemplateTest<a_type, another_type> (); TemplateTest<a_type, int_type> struct2 = TemplateTest<a_type, int_type> (); #else // workarounds : // use parentheses std::array<void*, SIZE_1> array1 = (std::array<void*, SIZE_1>({nullptr})); // explicitly write out the value std::array<void*, SIZE_2> array2 = std::array<void*, 2>({nullptr}); // use a cast std::array<void*, SIZE_3> array3 = std::array<void*, static_cast<size_t>(SIZE_3)>({nullptr}); // use a typedef typedef TemplateTest<a_type, another_type> fix_1; TemplateTest<a_type, another_type> struct1 = fix_1(); // use decltype TemplateTest<a_type, int_type> struct2 = decltype(struct2)(); // use int explicitly TemplateTest<a_type, int_type> struct2_alt = TemplateTest<a_type, int>(); #endif }; The compiler errors generated are of the form: test.cpp:22:55: error: expected ‘;’ at end of member declaration std::array<void*, SIZE_1> array1 = std::array<void*, SIZE_1>({nullptr}); ^ test.cpp:22:55: error: ‘std::array<void*, 1ul> Test::SIZE_1’ conflicts with a previous declaration test.cpp:17:9: note: previous declaration ‘Test::<anonymous enum> SIZE_1’ enum { SIZE_1 = 1 }; ^ test.cpp:22:61: error: expected unqualified-id before ‘>’ token std::array<void*, SIZE_1> array1 = std::array<void*, SIZE_1>({nullptr}); ^ test.cpp:22:72: error: expected unqualified-id before ‘)’ token std::array<void*, SIZE_1> array1 = std::array<void*, SIZE_1>({nullptr}); With some variations: test.cpp:24:55: error: declaration of ‘std::array<void*, 3ul> Test::SIZE_3’ [-fpermissive] test.cpp:3:14: error: changes meaning of ‘SIZE_3’ from ‘const size_t SIZE_3’ [-fpermissive] const size_t SIZE_3 = 3; test.cpp:23:52: error: wrong number of template arguments (1, should be 2) std::array<void*, SIZE_2> array2 = std::array<void*, SIZE_2>({nullptr}); It looks like the second template argument is being parsed as another variable name, a la the b in "int a = 1, b" Is this an inevitable consequence of some grammatical ambiguity, or is a fix possible?