是否可以通过extern链接重载函数?

ikh*_*ikh 5 c++ function linkage

我在声明中看到了一个奇怪的代码std::atexit:

extern "C"   int atexit( void (*func)() );
extern "C++" int atexit( void (*func)() ); // ... why are there two functions?
Run Code Online (Sandbox Code Playgroud)

我想这是某种函数重载,但它似乎显然是错误的.

那是什么?为什么有必要?

Lig*_*ica 4

你的源码有问题

这是 cppreference 有点误导。

使用不同的存储类说明符两次声明同一函数是非法的,并且会导致构建失败。如果您查看libstdc++(GCC 的标准库实现)的源代码,您会发现实际上只extern "C"提供了版本。


标准对此的看法

尽管[C++11: 18.5]与 cppreference 一样列出了这两个声明,但这并不意味着两者都可以在单个实现中使用;这意味着实现可以选择声明其中任何一个:也就是说,它说明了[C++11: 17.6.4.3.3/4]:

使用外部链接声明的标准 C 库中的每个函数签名都保留给实现,用作具有 extern“C”和 extern“C++”链接的函数签名[..]

还:

[C++11: 17.6.2.3/2]:使用外部链接声明的 C 标准库中的名称是否具有extern "C"或extern "C++"链接是实现定义的。建议实现extern "C++"为此目的使用链接

该规则在这里明确明确:

[C++11: 7.5/5]:如果两个声明将具有相同名称和参数类型列表(8.3.5)的函数声明为同一名称空间的成员,或者将具有相同名称的对象声明为同一名称空间的成员,并且声明为名称提供了不同的语言链接,程序格式错误;如果声明出现在不同的翻译单元中,则不需要诊断。[..]


为什么这可能会令人困惑

在我看来,这确实会在标准的其他地方引起一些问题;例如:

[C++11: 25.5/2]:内容与标准 C 库头相同,<stdlib.h>但有以下例外:

[C++11: 25.5/3]:函数签名:

bsearch(const void *, const void *, size_t, size_t,
        int (*)(const void *, const void *));
Run Code Online (Sandbox Code Playgroud)

被两个声明替换:

extern "C" void *bsearch(const void *key, const void *base,
                         size_t nmemb, size_t size,
                         int (*compar)(const void *, const void *));

extern "C++" void *bsearch(const void *key, const void *base,
                           size_t nmemb, size_t size,
                           int (*compar)(const void *, const void *));
Run Code Online (Sandbox Code Playgroud)

两者的行为都与原始声明相同。

我认为这是语言缺陷。