GCC 和 Clang 都不完全符合 C++ 标准。
Neither GCC nor Clang are compliant with standard C++

原始链接: https://sebsite.pw/w/20260708-badstdcxx.html

在 C++ 中,标准规定具有不同语言链接(例如 "C" 与 "C++")的函数类型是不同的,即使它们的签名完全相同。此规定旨在应对调用约定可能存在的差异。 然而,GCC 和 Clang 并不在函数类型中存储语言链接信息。因此,它们将 "C" 和 "C++" 函数类型视为相同,这会导致 `static_assert` 检查失败,并在重载接受这些指针的函数时引发错误的编译报错。 虽然这种行为违反了 C++ 标准,但编译器实际上已无法更改。改变其实现方式将构成破坏性的 ABI 变更;况且在几乎所有现代平台上,C 和 C++ 的调用约定完全一致,因此几乎没有实际动力去修改这一实现。归根结底,这表明 C++ 标准本身已与现代实际情况脱节。作者认为,语言链接应被定义为依赖于具体实现,而非强制执行,并承认编译器除了维持现状这种不符合标准的形式外别无选择。

最近的一场 Hacker News 讨论指出,GCC 和 Clang 等主流编译器并未完全严格遵守 C++ 标准。评论者指出,这并非新问题;编译器往往优先考虑实用性、可交付的代码以及特定平台的性能,而非严格遵循规范。 这场讨论演变为一场关于系统编程现状的更广泛争论: * **标准与现实:** 有人认为,由于高质量的开源编译器已具备广泛的可移植性,语言标准已经失去了其团结不同供应商的初衷。 * **C++ 的复杂性:** 该语言极其庞大,导致开发者往往使用不同的“方言”或子集,从而引发兼容性和招聘方面的摩擦。 * **现代替代方案:** 教育者和开发者讨论了 Rust 和 Zig 等新语言的优点。尽管支持者提倡更安全、更现代的设计,但质疑者认为,对于复杂的性能关键型系统以及 GPU 编程等特定领域,C++ 仍然是“阻力最小”的选择,因为这些领域有着深度绑定 C++ 的硬件专用工具链。 最终,参与者们承认,虽然系统编程需要处理深奥的技术细节,但语言的选择始终是在现代安全性与根深蒂固的生态系统支持之间的一种权衡。
相关文章

原文

in c++, function types have a "language linkage" associated with them: this is either "C++", "C", or some other implementation-defined language. and the standard very explicitly states that Two function types with different language linkages are distinct types even if they are otherwise identical. the idea is that some implementations may have different calling conventions for c++ functions than for c functions, so they can't be intermixed

gcc and clang however, just, don't store language linkage information with the type. so two functions with different language linkages can be identical:

#include <type_traits>
extern "C" using c_func = void ();
// this static assertion should fail, but it doesn't
static_assert(std::is_same<c_func, void ()>::value);

this can also cause erroneous compilation failures when overloading a function which takes in a function pointer parameter:

extern "C" using c_func = void ();
void f(c_func *) {}
void f(void (*)()) {}

the above code should compile, but gcc and clang both think that the parameter lists are identical and thus this violates the one definition rule

IMO the blame here doesn't lie on gcc or clang; it lies on the standard. that is, the standard is wrong and should be updated to make this implementation-defined. gcc and clang can't change their behavior because that would be a breaking ABI change (extern "C" function types in mangled names would be encoded differently). and they have no reason to make this change: the calling conventions for c and c++ are identical on, as far as i can tell, pretty much every platform

联系我们 contact @ memedata.com