为什么我的日志中的std名字空间?(Why is my log in the std namespa

2019-06-17 17:10发布

在下面的代码,我定义了一个简单的log功能。 在main我尽量把它; 我打电话std::log 。 不过,我自己的log被调用; 我看到“登录!” 在屏幕上。 有谁知道为什么吗? 我用G ++ 4.7和铛++ 3.2。

#include <iostream>
#include <cmath>

double log(const double x) { std::cout << "log!\n"; return x; }

int main(int argc, char *argv[])
{
  std::log(3.14);
  return 0;
}

Answer 1:

C ++标准17.6.1.2第4(重点煤矿):

除了通过30和附件d如项18所指出的,每一个报头的内容cname应是相同的与对应的标题的name.h ,如在C标准库(1.2)或C- Unicode的TR指定,如适当,仿佛被列入。 在C ++标准库,但是,声明(除了其被定义为在C宏名称)是命名空间的命名空间范围(3.3.6)内std它是不确定是否这些名称是全局命名空间范围内的第一个声明,然后注入到命名空间std通过明确的使用申述 (7.3.3)。

克++做它后者方式,使一些相同头文件可以为C和C ++进行再利用。 因此,G ++允许声明和定义double log(double)在全局命名空间。

第17.6.4.3.3第3和4:

从外部链接声明的标准C库中的每个名称被保留,以用作同一个名字的实施extern "C"联动,无论是在命名空间std ,并在全局命名空间。

从外部链接声明的标准C库的每个功能的签名被保留到实现用作具有两种功能:签名extern "C"extern "C++"联动,或在全局命名空间的命名空间范围的名称。

而在达第17.6.4.3条第2款的顶部:

如果程序声明或在它是保留一个上下文定义了一个名字,除了由于明确本条款允许的,其行为是不确定的。

而你,另一方面,可能声明或定义::log以任何方式。

这太糟糕了G ++工具链不给你任何错误消息,但。



Answer 2:

会发生什么,我希望是, std::log干脆委托给::log 。 不幸的是, ::log只是提供了一个float过载,你请提供一个double过载,使你更好的匹配。 但我还是不明白如何它甚至获取重载集合考虑。



Answer 3:

上的libstdc ++的cmath你会看到:

using ::log;

因此它带来的math.h中的功能从全局命名空间为std 。 不幸的是你提供了一个实现double log(double) ,因此链接器将不使用来自数学lib中的一个。 所以肯定是在的libstdc ++的错误

编辑:我要求它在一个的libstdc ++的bug,因为std::log不应与C库干扰,当你明确要求对遭受std::版本。 当然,这种方式重写标准库函数是C语言的一个古老的“功能”。

编辑2:我发现,该标准实际上并不禁止将名称从全局命名空间为std 。 所以,毕竟不是一个错误,只有实现细节的结果。



Answer 4:

在C ++中,编译器就可以实现在全局命名空间的C库,并委托给它(这是实现定义)。

17.6.1.2.4通过除30和附件d如项18所指出的,每一个报头的CNAME的内容应是相同于相应的头name.h的,如在C标准库SPECI音响ED(1.2)或C- Unicode的TR,在适当时,如果被列入。 在C ++标准库,但是,声明(除了其是定义为在C宏德音响名称)是命名空间std的命名空间范围(3.3.6)内。 这是unspeci网络版是否这些名字第一个全局命名空间范围内声明的,然后通过使用明确的-声明 (7.3.3) 注入空间std。

在一般情况下,我会避免函数具有相同签名的C标准库之一。 C ++标准当然给编译器可以自由地使用这些特征如果选择这种方式,这意味着如果你尝试使用相同的签名,你可能会打你的编译器。 因此,你得到奇怪的结果。

我希望链接错误或警告,虽然,我认为这可能是值得我们举报。

[编辑]

哇,ninja'd。



Answer 5:

因为你已经在全局命名空间覆盖它。 使用命名空间避免了危险的,如果你不想要移动到像一个更安全,更清洁的语言稔的例子。

正确使用命名空间演示 :

#include <iostream>
#include <cmath>  // Uses ::log, which would be the log() here if it were not in a namespace, see http://stackoverflow.com/questions/11892976/why-is-my-log-in-the-std-namespace

// Silently overrides std::log
//double log(double d) { return 420; }

namespace uniquename {
    using namespace std;  // So we don't have to waste space on std:: when not needed.

    double log(double d) {
        return 42;
    }

    int main() {
        cout << "Our log: " << log(4.2) << endl;
        cout << "Standard log: " << std::log(4.2);
        return 0;
    }
}

// Global wrapper for our contained code.
int main() {
    return uniquename::main();
}

输出:

Our log: 42
Standard log: 1.43508


文章来源: Why is my log in the std namespace?