11

如果我在某处定义一个命名空间log并使其在全局范围内可访问,这将与double log(double)标准cmath标题冲突。实际上,大多数编译器似乎都支持它——SunCC、MSVC、GCC 的大多数版本——但 GCC 4.1.2 没有。

不幸的是,似乎没有办法解决歧义,因为using命名空间标识符的声明是不合法的。log::Log即使包含在内,您知道我可以在全局命名空间中写入的任何方式cmath吗?

谢谢。

编辑:有人知道 C++03 标准对此有什么看法吗?我会认为范围运算符充分消除了log在下面的代码示例中使用的歧义。

#include <cmath>

namespace foo
{

namespace log
{

struct Log { };

} // namespace log

} // namespace foo


using namespace foo;

int main()
{
    log::Log x;

    return 0;
}

// g++ (GCC) 4.1.2 20070115 (SUSE Linux)

// log.cpp: In function `int main()':
// log.cpp:20: error: reference to `log' is ambiguous
// /usr/include/bits/mathcalls.h:110: error: candidates are: double log(double)
//     log.cpp:7: error:                 namespace foo::log { }
// log.cpp:20: error: expected `;' before `x'
4

4 回答 4

12

我建议:

foo::log::Log x; // Your logging class
::log(0.0); // Log function

一般来说,我不会写,因为如果你不打算使用它并且它会污染全局命名空间,那么将using namespace foo;它放在命名空间中是没有意义的。foo

请参阅此相关问题:
如何在 C++ 中正确使用命名空间?

于 2010-10-06T10:28:06.410 回答
8

虽然它对您没有帮助,但来自 GCC 4.1.2 的错误是不正确的。loginlog::Log只能引用类或命名空间名称。

如果您的代码还需要使用 GCC 4.1.2 进行编译,那么有两种选择:

  1. 使用完全限定名称foo::log::Log
  2. 使用命名空间别名:

    namespace log1 = foo::log;
    log1::Log logger;
于 2010-10-06T10:37:18.043 回答
1

cmath出于某种原因使用::log从全局范围获取它并且无法在函数和您的命名空间之间做出决定。

命名空间保留代码以防止混淆污染函数签名。

这是正确使用 命名空间的完整且记录在案的演示:

#include <iostream>
#include <cmath>  // Uses ::log, which would be the log() here if it were not in a namespace, see https://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
于 2015-05-06T03:17:04.637 回答
0

在 c++0x 或 c++11 中,以下应该可以工作,使用 -std=c++0x 或 -std=c++11 编译:

#include <iostream>
#include <math.h>

namespace ___ {
namespace log {

void init() {
    std::cout << "log::init()" << std::endl;
}

} // namespace log
} // namespace ___

using namespace ___;

int main() {
    log::init();
    std::cout << ::log(3.2) << std::endl;
    return 0;
}
于 2021-05-29T14:10:49.920 回答