c++ - 为什么 Clang 和 MSVC 不喜欢带有一组冗余括号的成员 typedef 声明?
问题描述
考虑
using foo = int;
struct A {
typedef A (foo)();
};
GCC 和 ICC 接受该片段,而 Clang 和 MSVC 拒绝它。Clang 的错误信息是
<source>:4:15: error: function cannot return function type 'void ()' typedef A (foo)(); ^ <source>:4:13: error: typedef name must be an identifier typedef A (foo)(); ^ 2 errors generated.
MSVC 说
<source>(4,15): error C2091: function returns function typedef A (foo)(); ^
(现场演示)
为什么 Clang 和 MSVC 会产生此错误?哪些编译器是正确的?
(我专门从标准或任何缺陷报告中寻找报价。)
解决方案
Clang 和 MSVC 都忽略了typedef
说明符并将声明读取为构造函数的声明(即A
构造函数名称),接受参数类型(foo)
(即(int)
)并“返回”由尾括号表示的函数类型()
。
是的,构造函数没有返回类型;但是如果他们确实有返回类型,他们就会有返回类型A
,所以最后的附加()
项使这些编译器认为你现在有一个返回类型为函数类型的构造函数A()
。
注意到以下“类似”声明具有类似的错误消息来支持这一点:
A (foo)();
typedef ~A(foo)();
此外,通过添加,static
我们可以从 MSVC 中获得一个启发性的错误消息:
A static (int)();
error C2574: '(__cdecl *A::A(int))(void)': cannot be declared static
对于解决方法:在 Clang(但不是 MSVC)下,您可以将说明typedef
符移到右侧,或使用详细的类型说明符:
A typedef (foo)();
typedef struct A (foo)();
在所有编译器下,您都可以删除或添加括号:
typedef A foo();
typedef A ((foo))();
而且您始终可以更新为类型别名:
using foo = A();
推荐阅读
- python - Python删除空键和空键不会影响我的对象
- python - OpenCV 3.4.1 错误 readNetFromTensorflow Can't open .pb in cv::dnn::ReadProtoFromBinaryFile
- wpf - 如何连接 WPF 和 WebAPI
- kubernetes - Kubernetes可以管理硬件设备吗?
- python - 模板不存在错误...在运行 manage.py 时出现 Django 错误
- python - 在 Python 3 中迭代图像的问题
- javascript - 为什么当 readonly=true 时使用 Javascript 分配给 Primefaces inputText 小部件的值不会发送到服务器?
- elasticsearch - 将 AWS Appsync 与 DynamoDB 结合使用,您是否应该通过将相关数据的“冗余副本”存储在同一个表上来建模关系(非规范化)?
- reactjs - 将 Asp.Net Core 的 React + Redux 入门模板中的入口点更改为控制器
- reactjs - 当更改一个特定的状态设置时,是否有必要重述所有其他状态设置?