Как разрешить конфликт имен между пространством имен C ++ и глобальной функцией? - PullRequest
10 голосов
/ 06 октября 2010

Если я определю пространство имен 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'

Ответы [ 3 ]

11 голосов
/ 06 октября 2010

Я бы предложил:

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

Как правило, я бы не стал писать using namespace foo;, поскольку нет смысла иметь его в пространстве имен foo, если вы не собираетесь его использовать, и онозагрязняет глобальное пространство имен.

Смотрите этот связанный вопрос:
Как правильно использовать пространства имен в C ++?

7 голосов
/ 06 октября 2010

Хотя это не помогает, ошибка из GCC 4.1.2 неверна. log в log::Log может ссылаться только на имя класса или пространства имен.

Если ваш код также должен быть скомпилирован с GCC 4.1.2, то есть два варианта:

  1. Используйте полное имя foo::log::Log
  2. Использовать псевдоним пространства имен:

    namespace log1 = foo::log;
    log1::Log logger;
0 голосов
/ 06 мая 2015

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
...