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?

Reply via email to