2010-10-06 126 views
9

如果我在某个地方定义了一个名称空间log并使其在全局范围内可访问,则将与标准cmath标头中的double log(double)冲突。实际上,大多数编译器似乎都遵循它 - SunCC,MSVC,GCC的大多数版本 - 但GCC 4.1.2不支持。如何解决C++名称空间和全局函数之间的名称冲突?

不幸的是,似乎没有办法解决歧义,因为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' 
+0

为什么不只是把它写为'富::登录:: Log'防止ambiguousity ? – 2010-10-06 10:25:13

+0

'Log'不是'foo :: log'的唯一成员,这里有很多。但是,是的,如果没有其他方法,我可能会完全排除所有这些问题。 – 2010-10-06 10:28:35

+0

@cj:你可能想看看[这个答案](http://stackoverflow.com/questions/2879555/c-stl-how-to-write-wrappers-for-cout-cerr-cin-and -endl/2880136#2880136)。 – sbi 2010-10-06 10:34:07

回答

10

我建议:

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

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

请参阅此相关的问题:
How do you properly use namespaces in C++?

7

虽然它不能帮助你,从GCC 4.1.2的错误是不正确。 log::Log中的log只能引用类或名称空间名称。

如果你的代码也需要与GCC 4.1.2编译,则有两种选择:

  1. 使用完全合格的名称foo::log::Log
  2. 使用空间别名:

    namespace log1 = foo::log; 
    log1::Log logger; 
+1

+1表示使用别名的想法。你确定错误是不正确的吗?我认为你的意思是范围操作符解决了歧义,因为它不能应用于函数名?我不确定关于这种特殊情况的标准是什么,但关于名称空间定义,请参见第7.3.1节:“原始名称空间定义中的标识符不应先在声明区域中定义, -namespace-definition出现。“ – 2010-10-06 10:51:40

+1

我相信错误是不正确的。我必须在标准中查找它,根据语法,只有类或名称空间名称可以在范围运算符之前出现。你的'log'命名空间的声明不是一个问题,因为它不是和'log'函数在同一个名字空间中定义的。 (命名空间使用'foo'命名空间,函数使用全局命名空间) – 2010-10-06 14:01:11

0

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

命名空间保留代码以防止功能签名的confusionpollution

#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(); 
} 

输出:propernamespace使用的

Here“SA完整和记录演示

Our log: 42 
Standard log: 1.43508 
相关问题