打印功能地址...声明?

Edg*_*jān 5 c++

考虑以下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.2clang 5.0都会产生警告,但编译并链接程序.

同时,Visual Studio 15.5.6没有链接此示例.

就个人而言,我预计,尽管使用的编译器foo似乎是使用ODR,但此代码根本不会链接.

有人可以解释为什么gccclang能够链接该程序吗?

Sto*_*ica 7

这是ODR违规.但根据[basic.def.odr]/10,强调我的:

每个程序应该只包含每个非内联函数或变量的一个定义,该函数或变量在废弃语句之外的程序中使用.无需诊断.该定义可以在程序中明确显示,可以在标准或用户定义的库中找到,或者(在适当的时候)隐式定义(参见[class.ctor],[class.dtor]和[class.copy] ]).内联函数或变量应在每个翻译单元中定义,在翻译单元中,在废弃的语句之外使用它.

我们必须记住,编译器可以自由地假设您不会编写表现出未定义行为的代码,或者以其他方式不需要诊断的格式错误.因为每个函数必须具有非null的地址,bool所以只能调用重载true,因为转换必须在有效程序中产生.

我们可以看到GCC 7.3正是这样做的.它通过1表示转换的结果,即使在-O0.