我可以依靠我的编译器来诊断 TU 中的类型不匹配吗?
Can I rely on my compiler to diagnose type mismatches within a TU?
在搜索规范时,似乎我的编译器不需要诊断以下错误
:extern int a;
extern float a;
我以前认为我的编译器需要诊断这一点,但规范说(我添加了重点)
在对类型进行所有调整之后(在此期间 typedefs (7.1.3) 被其定义替换),引用给定变量或函数的所有声明指定的类型应相同,除了数组对象的声明可以指定因是否存在主数组绑定 (8.3.4) 而不同的数组类型。违反此类型标识规则不需要诊断。
事实上,我发现了编译器不在乎的情况。例如,GCC 和 clang 接受以下内容
void g() { int f(); }
void h() { float f(); }
由于违反不需要诊断的规则意味着整个程序不再需要诊断,这意味着以下格式错误的程序也不需要诊断(请参阅 1.4p2)。幸运的是,GCC和Clang都诊断出它们。
int f();
float f();
此代码在翻译时的行为实际上是未定义的。这是什么原因呢?为什么规范不能要求拒绝此类情况并要求对其进行诊断?
我认为你引用的规则是谈论整个程序。如果一个 TU 有extern int a;
而另一个 TU 有extern float a;
,则不需要诊断,因为单独的翻译使其不可能 - 问题最多只能在链接时检测到。
但是,如果两个声明都发生在单个 TU 中,我确信需要进行诊断。也许是 3.3/4?这(大致)要求一个范围内名称的所有声明都引用同一实体。
对于你的第一个示例,Visual Studio(正确地)启动:
d:experimentstest1test1test1.cpp(7) : error C2371: 'a' : redefinition; different basic types
d:experimentstest1test1test1.cpp(6) : see declaration of 'a'
您的第二个示例没有错,因为函数定义是本地的,因此它们可以做任何他们喜欢的事情。
你的第三个示例(正确地)在Visual Studio中引发了一个错误:
d:experimentstest1test1test1.cpp(7) : error C2556: 'float f(void)' : overloaded function differs only by return type from 'int f(void)'
d:experimentstest1test1test1.cpp(6) : see declaration of 'f'
d:experimentstest1test1test1.cpp(7) : error C2371: 'f' : redefinition; different basic types
我确信规范说您不能在同一作用域中有多个同名变量,并且同一作用域中的函数定义必须相差大于其返回类型。
根据 Pete Becker 的说法,当你有像 §1.4/2 中的项目符号这样的规则列表时,它们(至少正常情况下)是按顺序阅读的,早期规则优先于后来的规则。
换句话说,如果代码同时违反了第二个和第三个项目符号点,则违反第二个项目符号点需要发出诊断,即使违反第三个项目符号点似乎消除了该要求。
不幸的是,我从未在标准版中看到过任何明确的声明,只有在Pete的旧Usenet帖子中(如果没记错的话,也许还有Pete之前的编辑Andrew Koenig)。
看起来像是沉重的数学问题。我的猜测是,原因是使用两个不同的 typedef,您最终可能会在两个不同的表达式中使用相同的类型。但是,当编译器存储数据结构时,要求检查将要求编译器将类型表达式"计算"为其正常形式。需要在编译器内部使用丘奇-罗瑟定理来证明这两个表达式是等价的。typedefs 中使用的操作只是普通的旧替换,因此需要完整的教堂罗斯。所以猜猜他们把它变成了可选的。我认为他们不想添加 lambda 演算,接下来需要这样做。
typedef A<int> C;
typedef int D;
typedef A<D> E;
extern C v;
extern E v;
现在,如果不评估两者A<int>
,就无法检查它们是否是同一类型。
- 将 unordered_map 与 Catch2 谓词一起使用时类型不匹配
- 重载函数的地址与所需类型不匹配
- 参数错误可能与类型不匹配有关?
- 调用子例程时类型不匹配
- POSIX(C )参数类型不匹配
- typedef 类型不匹配,将其传递到函数中
- 为什么此代码编译 (C++11) 而没有类型不匹配错误
- 候选模板被忽略:推断的类型与调整后的类型不匹配
- 内联 ASM:'out'的操作数类型不匹配
- 为什么我们有一个类型不匹配
- C++类和freeglut(参数类型不匹配)
- 警告 639:二进制操作中类型 'uint64' 的强类型不匹配
- 警告 634:相等或有条件的强类型不匹配(类型"bool")
- 不了解C++类型不匹配:const Foo* to Foo* const&
- 函数声明和定义的返回类型不匹配,编译器可以吗?
- 类型不匹配
- 返回指向常量getter的指针时,返回值类型与函数类型不匹配
- llvm pass replaceAllUses与类型不匹配?
- 参数类型不匹配(无效*)
- 重载运算符中的类型不匹配(写入管道)