与在新表达式中解析类型 ID 相关的 gcc 发出错误
Posted
技术标签:
【中文标题】与在新表达式中解析类型 ID 相关的 gcc 发出错误【英文标题】:An error is issued by gcc relative to parsing type-id in a new expression 【发布时间】:2019-09-14 12:29:28 【问题描述】:这个程序
#include <cstddef>
int main()
const std::size_t N1 = 2;
const std::size_t N2 = 3;
int ( **p )[N1] = new ( int ( *[N2] )[N1] );
does not compile 使用编译器 C++ gcc HEAD 10.0.0 20190。
编译器报错
prog.cc: In lambda function:
prog.cc:8:40: error: expected '' before ')' token
8 | int ( **p )[N1] = new ( int ( *[N2] )[N1] );
| ^
prog.cc: In function 'int main()':
prog.cc:8:34: error: no match for 'operator*' (operand type is 'main()::<lambda()>')
8 | int ( **p )[N1] = new ( int ( *[N2] )[N1] );
prog.cc:8:47: error: expected type-specifier before ';' token
8 | int ( **p )[N1] = new ( int ( *[N2] )[N1] );
| ^
但是程序使用 clang HEAD 10.0.0 编译。
指针类型-id 规范是模棱两可的还是确实是 gcc 错误?
EDIT:顺便说一下如果去掉外括号,比如
int ( **p )[N1] = new int ( *[N2] )[N1];
然后 clang 也会发出一个引用 lambda 的错误
prog.cc:8:38: error: expected body of lambda expression
int ( **p )[N1] = new int ( *[N2] )[N1];
^
【问题讨论】:
“在 lambda 函数中”? @max66 我照原样复制了错误消息。 我明白了...我只是很惊讶。另一个“最令人头疼的解析”问题?但我不明白编译器如何从您的代码中检测到 lambda。 g++错误从9.1.0版本开始,根据wandbox;之前没有错误。有趣的是,你在编译 C++98 时也有同样的错误(关于 lambda 函数)。 如果您使用2
而不是N1
,g++ 错误仍然存在。但如果你使用3
而不是N2
,就会消失。
【参考方案1】:
据我所知,这绝对是最新版本的 GCC 中的一个错误。据推测,GCC 正试图将( int ( *[N2] )[N1] )
部分解析为new-placement,即带括号的表达式列表。现在int (
被解释为函数式转换等。
每new-expression:
新表达式:
::
optnew
new-placementoptnew -type-id new-initializeropt::
optnew
new-placementopt(
type-id)
new-initializeropt
对于 new-placement 与 (
type-id )
没有特殊的消歧规则,因此应该将其解释为 type -id 如果它不能被解释为一个表达式列表。
EDIT 部分是每个[expr.new]/4 的语法错误:
[ 注意: new-expression 的 new-type-id 中的括号会产生令人惊讶的效果。 [ 示例:
new int(*[10])(); // error
格式不正确,因为绑定是
(new int) (*[10])(); // error
相反,new
运算符的显式括号版本可用于创建复合类型的对象:
new (int (*[10])());
分配一个包含 10 个函数指针的数组(不带参数并返回 int
)。
—结束示例]
——尾注]
【讨论】:
【参考方案2】:这可能不是您要寻找的答案,但真正的答案是:
using T = int(*)[N1];
T *p = new T[N2];
一旦你有多个声明符,C 和 C++ 使用的基于声明符的语法实际上是不可能理解的。他们很难写...你把括号放在哪里?顺序是什么?而且它们很难阅读...不能从左到右,不能从右到左,必须由内向外旋转。
只需使用别名。易写、易读、易解析。
【讨论】:
谢谢。我知道这个。但有趣的是如何在不使用 typedef 或别名声明的情况下指定类型。以上是关于与在新表达式中解析类型 ID 相关的 gcc 发出错误的主要内容,如果未能解决你的问题,请参考以下文章