考虑以下MCVE:
#include <iostream>
int main()
{
void foo(int);
std::cout << foo << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
在这里,我故意尝试以错误的方式打印指向函数的指针,以便选择接受的操作符<< overloadbool
.
basic_ostream& operator<<( bool value );
Run Code Online (Sandbox Code Playgroud)
令我困惑的是,gcc 7.2和clang 5.0都会产生警告,但编译并链接程序.
同时,Visual Studio 15.5.6没有链接此示例.
就个人而言,我预计,尽管使用的编译器foo
似乎是使用ODR,但此代码根本不会链接.
有人可以解释为什么gcc和clang能够链接该程序吗?
这是ODR违规.但根据[basic.def.odr]/10,强调我的:
每个程序应该只包含每个非内联函数或变量的一个定义,该函数或变量在废弃语句之外的程序中使用.无需诊断.该定义可以在程序中明确显示,可以在标准或用户定义的库中找到,或者(在适当的时候)隐式定义(参见[class.ctor],[class.dtor]和[class.copy] ]).内联函数或变量应在每个翻译单元中定义,在翻译单元中,在废弃的语句之外使用它.
我们必须记住,编译器可以自由地假设您不会编写表现出未定义行为的代码,或者以其他方式不需要诊断的格式错误.因为每个函数必须具有非null的地址,bool
所以只能调用重载true
,因为转换必须在有效程序中产生.
我们可以看到GCC 7.3正是这样做的.它通过1表示转换的结果,即使在-O0
.
归档时间: |
|
查看次数: |
109 次 |
最近记录: |