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?