Использование функций из глобального пространства имен в пространстве имен - PullRequest
2 голосов
/ 16 февраля 2020

Я использую библиотеку, которая находится в пространстве имен, давайте назовем ее Hello.

namespace Hello {

template<class T>
void World(std::ostream& os, const T& t) {
    os << t;
}

}

class T - это что-то вроде std::array<int,10>, и я также пишу для него функцию перегрузки ostream. Однако вызов Hello::World(arr) приводит к ошибкам компиляции, из-за которых компилятору не удается найти перегрузку для operator<<().

. После некоторого поиска я нашел решение, объясняющее эту ситуацию. Как работает разрешение перегрузки оператора в пространствах имен? и Разрешение имен функций внутри шаблонов, созданных с помощью квалифицированных типов .

Таким образом, мы можем упростить ситуацию следующим образом.

void f(int) {}
void f(int,int) {}

namespace Hello {
    using ::f;
    void f(int,int,int) {}
    void World()
    {
        f(100);
        f(100, 200);
        f(100, 200, 300);
    }
};

int main()
{
    Hello::World();
    return 0;
}

Без строки using ::f; этот код не может быть скомпилирован, поскольку имя f может скрывать ВСЕ функции с одинаковыми именами в глобальном пространстве имен.

Теперь, когда это мои проблемы:

  1. Поскольку namespace Hello { .... } находится в библиотеке, я не буду ее изменять. То есть я не могу изменить реализацию внутри World(). Единственное решение - поместить строку namespace Hello { using ::f; } где-нибудь в моем коде. Это хорошая практика или есть более элегантное решение?
  2. В этом примере я могу импортировать только f(int), а не f(int,int)?

1 Ответ

2 голосов
/ 16 февраля 2020

Это хорошая практика или есть более элегантное решение?

ИМХО, вы можете использовать его со сторонней библиотекой. Это понятно и достаточно выразительно. Было бы лучше, если бы вы могли написать:

void World() {
    ::f(100);           // f from global namespace
    ::f(100, 200);      // f from global namespace
    f(100, 200, 300);   // f NOT from global namespace
}

, потому что тогда ясно видно, какая функция равна , а какая не является из глобального пространства имен, но это решение у вас не работает, так как вы не можете изменить реализацию функции World.

Могу ли я импортировать только f(int), а не f(int, int)?

Да. Чтобы импортировать только f(int) функцию, вы можете сделать следующее:

void f(int) {}

namespace Hello {
    using ::f;    // only void f(int) is defined before this line
                  // therefore, it is the only overload being imported to the Hello namespace
}

void f(int,int) {}

Демо

ОБНОВЛЕНИЕ

Если вы хотите импортировать только одну перегрузку operator<<, а не обычной функции, тогда вы можете заключить каждую перегрузку в отдельное пространство имен, например:

namespace XX {

struct X {
    int x;
};

std::ostream& operator<<(std::ostream& os, X const& x) {
    return os;
}

}

namespace YY {

std::ostream& operator<<(std::ostream& os, Y const& y) {
    return os;
}

struct Y {
    double y;
};

}

namespace Hello {
    using ::XX::X;
    using ::XX::operator<<;
    using ::YY::Y;
}

Проверьте это live .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...