【问题标题】:expected primary-expression before ‘struct’“结构”之前的预期主表达式
【发布时间】:2020-08-11 00:37:23
【问题描述】:

GCC 8.3.0 和 clang 9.0.1 都无法编译这个简短的示例代码:

#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);
}

出现的错误信息:

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.
               ^

我不明白为什么第一个表达式似乎是某种非法语法。

据我所知,struct 关键字在 C++ 中基本上可以省略除非有歧义。这往往会发生(例如,对于[struct] stat,它可以是结构或函数),因此struct 关键字可以而且应该用于在这种情况下消除歧义。

然而,在我的示例中,使用 struct 关键字是完全有害的,我从没想过会这样。

由于两个不同的编译器以完全相同的方式拒绝代码,我最好的猜测是我遗漏了一些信息,而不是这是一个错误。

【问题讨论】:

  • 只是猜测,但我相信您只是在调用 mystruct 的构造函数,因此将 struct 关键字放在那里对编译器没有意义。这段代码我得到了同样的错误:struct test { int data; } int main() { auto temp = struct test; }
  • 可以加括号为auto elem1 = (struct mystruct&lt;bool&gt;) { };
  • 是的,但没有。我正在创建一个 [struct] mystruct 类型的新对象,初始化为初始化列表中提供的值(恰好是空的,所以初始化为零),然后将其复制到原始变量中。当然,副本是多余的,但这不是重点。但是,到目前为止,您的观点感兴趣的是编译器可能不会将 struct mystruct&lt;T&gt; 视为一种类型,而是将其视为其他东西,这可以通过将类型包装在括号中来解决。不过……这听起来很奇怪。
  • 这对于创建任何多字类型的临时文件都是一样的。 f(long long{1}) fails similarly.
  • @songyuanyao:这是一个复合文字,不是 C++(但通常支持 C99 兼容性)。

标签: c++ struct


【解决方案1】:

type{…} 语法与type(…) 一样,需要一个单一、未详细说明的类型说明符。这可能相当复杂:

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

但是,它不能包含运算符或前缀说明符:

// 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

这种情况当然可以通过decltype或者引入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);
}

【讨论】:

  • [dcl.typedef]中定义,typedef-name中simple-template-id中的template-name应该是单个标识符。
  • @yao99:听起来不错,但我不确定你想从中得出什么结论。
  • 只需将链接粘贴到文档。 :)
猜你喜欢
  • 2016-07-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-16
  • 2018-12-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多