c++ - 当我们调用 C 函数时,为什么不抛出编译器时间错误

标签 c++ c

根据标准在 N4296::13.3.3 [over.match.best] 中提供的示例

namespace A 
{
    extern "C" void f(int = 5);
}

namespace B 
{
    extern "C" void f(int = 5);
}

using A::f;
using B::f;

void use() 
{
    f(3); // OK, default argument was not used for viability
    f(); // Error: found default argument twice
}

正如标准在 N4296::7.5/6 [dcl.link] 中所说:

Two declarations for a function with C language linkage with the same function name (ignoring the namespace names that qualify it) that appear in different namespace scopes refer to the same function.

我试着用我自己的例子来探索这样的事情:

#include <iostream>

namespace A
{
    extern "C" void foo(int a = 5){ std::cout << a << "1" << std::endl; }
}

namespace B
{
    extern "C" void foo(int a = 5);
}

using A::foo;
using B::foo;

int main()
{ 
    foo(); //Error 
    foo(2);
}

DEMO

那么为什么我的示例有效?除非我在 A 命名空间中明确定义函数,否则我的示例和标准示例之间有什么区别?为什么这如此重要?

最佳答案

如评论中所述,标准示例与您的示例之间没有相关差异。正确实现标准的编译器会为两者发出诊断。

事实是,至少在 clang 和 Intel 中这显然是一个编译器错误,当您将示例编辑为无意义时可以看出这一点

namespace A
{
    extern "C" void f(int = 5);
}

namespace B
{
    extern "C" void f(int = 3); // different default argument
}

using A::f;
using B::f;

void use()
{
    f(); // No error !
}

尽管有两个不同 默认参数,但不会生成错误甚至警告。使用其中一个默认参数,第一个用于 Intel,第二个用于 clang。

GCC 确实拒绝了这个荒谬的例子,所以没有快速简便的方法来验证它是否也是 GCC 中的一个错误,但这并没有改变它是的事实:如前所述,它默默地接受标准中的示例,其中标准指出应检测错误的位置。

关于c++ - 当我们调用 C 函数时,为什么不抛出编译器时间错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27683995/

相关文章:

c++ - 接收(MSG_PEEK)超时

c++ - 将 std::set 或 std::map 与共享内存一起使用

c++ - 许多类变量的 pthread

c - 为什么每当输入非整数类型时我都会不断得到一个无限循环?

c - 如何查看线路是否结束?

c - 如何将数组中的字符串转换为无符号整数?

c++ 测试 double * double 是否会溢出 uint64_t

c++ - 未检测到温度文件的变化

c - 我怎样才能把不同的数字放在 C 上的 2 个数组中

c# - 透明Windows窗体,内部有OpenGL绘图