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

时间:2018-02-06 21:40:51

标签: c++

考虑以下MCVE:

#include <iostream>

int main() 
{
    void foo(int);
    std::cout << foo << std::endl;

    return 0;
}

这里我故意尝试以错误的方式打印指向函数的指针,以便选择接受bool的{​​{3}}。

 basic_ostream& operator<<( bool value );

让我感到困惑的是,operator<< overloadgcc 7.2都会产生警告,但编译并链接该程序。

同时, Visual Studio 15.5.6 不会链接此示例。

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

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

1 个答案:

答案 0 :(得分:7)

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

  

每个程序都应包含每个非内联的一个定义   在a之外的程序中使用的函数或变量   废弃的陈述; 无需诊断。定义可以   在程序中明确出现,可以在标准中找到或者   用户定义的库,或(在适当的时候)它是隐式定义的   (参见[class.ctor],[class.dtor]和[class.copy])。内联函数   或变量应在其所在的每个翻译单元中定义   在废弃的陈述之外使用。

我们必须记住,编译器可以自由地假设您不会编写表现出不确定行为的代码,或者以他们不需要诊断的方式编写错误的代码。由于每个函数的地址都必须为空,因此只能使用bool调用true重载,因为转换必须在中生成的内容才有效程序

我们可以看到GCC 7.3这样做。即使在-O0,即使在let searchController = UISearchController(searchResultsController: nil) override func viewDidLoad() { super.viewDidLoad() searchController.searchResultsUpdater = self searchController.obscuresBackgroundDuringPresentation = false searchController.hidesNavigationBarDuringPresentation = false definesPresentationContext = true navigationItem.searchController = searchController navigationItem.hidesSearchBarWhenScrolling = false } ,它也会传递1作为转换的结果。