How to resolve a name collision between a C++ namespace and a global function?

让人想犯罪 __ 提交于 2019-11-30 02:42:02

问题


if I define a namespace log somewhere and make it accessible in the global scope, this will clash with double log(double) from the standard cmath header. Actually, most compilers seem to go along with it -- most versions of SunCC, MSVC, GCC -- but GCC 4.1.2 doesn't.

Unfortunately, there seems no way to resolve the ambiguity, as using declarations are not legal for namespace identifiers. Do you know any way I could write log::Log in the global namespace even if cmath is included?

Thanks.

EDIT: Would anybody know what the C++03 standard has to say about this? I would have thought that the scope operator sufficiently disambiguates the use of log in the code example below.

#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'

回答1:


I'd suggest:

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

Generally I wouldn't write using namespace foo; as there is no point having it in the foo namespace if you're not going to use it and it pollutes the global namespace.

See this related question:
How do you properly use namespaces in C++?




回答2:


Although it does not help you, the error from GCC 4.1.2 is incorrect. The log in log::Log can only refer to a class or namespace name.

If your code also needs to compile with GCC 4.1.2, then there are two options:

  1. Use the fully qualified name foo::log::Log
  2. Use a namespace alias:

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



回答3:


cmath uses ::log for some reason to get it from the global scope and can't decide between the function and your namespace.

Namespaces keep code contained to prevent confusion and pollution of function signatures.

Here's a complete and documented demo of proper namespace usage:

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

Output:

Our log: 42
Standard log: 1.43508


来源:https://stackoverflow.com/questions/3871474/how-to-resolve-a-name-collision-between-a-c-namespace-and-a-global-function

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!