expected primary-expression before ‘struct’

Viewed 1633

Both GCC 8.3.0 and clang 9.0.1 fail to compile this short example code:

#include <cstdlib>

template <typename T>
struct mystruct {
  T data;
};

int main (const int argc, const char * const * const argv) {
  int ret = EXIT_SUCCESS;

  auto elem1 = struct mystruct<bool> { }; // Doesn't compile.
  auto elem2 = mystruct<bool> { }; // Does compile.

  return (ret);
}

Error messages that come up:

teststruct.cpp: In function ‘int main(int, const char* const*)’:
teststruct.cpp:11:16: error: expected primary-expression before ‘struct’
   auto elem1 = struct mystruct<bool> { }; // Doesn't compile.
                ^~~~~~
teststruct.cpp:11:16: error: expected expression
  auto elem1 = struct mystruct<bool> { }; // Doesn't compile.
               ^

I don't understand why the first expression seems to be some kind of illegal syntax.

As far as I know, the struct keyword can essentially be omitted in C++ unless there is ambiguity. This tends to happen (e.g., for [struct] stat, which can either be a structure or a function), so the struct keyword can and should be used to disambiguate in such scenarios.

In my example, however, using the struct keyword is downright harmful and I would have never expected that.

Since two different compilers are rejecting the code in exactly the same way, my best guess is that I'm missing some information, rather than this being a bug.

1 Answers

The type{…} syntax, like type(…), requires a single, non-elaborated type specifier. This can be fairly complicated:

auto x=typename A::template B<int>();  // OK

It cannot, however, include operators or prefix specifiers:

// All bad:
auto a=int*{};
auto b=const int();
auto c=struct X{};  // a class definition?
auto d=struct Y {}();  // still not allowed
auto e=signed char();

auto f=signed();  // OK, means int

Such cases can of course be handled by decltype or by introducing typedef-names:

void f(void());
void f(int*);
struct x {};
void g(x);
void g(unsigned long);
void h() {
  // Ambiguous:
  // f(nullptr);
  // Illustrative of the parsing difficulty:
  // f(void(*)()());
  f(decltype(&h)());
  int x;  // oh noes
  using y=struct x;
  g(y());
  g(decltype(1ul)());  // same as g(0);
}
Related