Есть ли проблема с использованием директивы в подробном пространстве имен?

Рассмотрим этот заголовок библиотеки:

#include<vector>
#include<algorithm>
#include<iostream>

namespace Lib {
  namespace detail {
    using namespace std;

    template<class T>
    void sort_impl(istream &in,ostream &out) {
      vector<T> v;
      {
        int n;
        in >> n;
        v.resize(n);
      }
      for(auto &i : v) cin >> i;

      sort(v.begin(),v.end());
      for(auto i : v) out << i << endl;
    }
  }

  inline void sort_std() {
    detail::sort_impl<int>(std::cin,std::cout);
  }
}

Успешно ли пространство имен detail изолирует клиентов библиотеки (и остальную часть реализации библиотеки) от using-directive в этом примере? Меня не интересует обсуждение на Почему использование пространства имен std считается плохим практика?, даже если некоторые из аргументов применимы даже к «хорошо сдержанным» директивам использования.

Обратите внимание, что есть два существующих вопроса, касающихся одной и той же ситуации, но с using-декларациями:

Это можно было бы сочетать с любым из них, но редактирование было бы серьезным.


person Davis Herring    schedule 12.09.2017    source источник
comment
Вы должны переместить using namespace std; в sort_impl. Тогда все будет в порядке.   -  person Henri Menke    schedule 12.09.2017
comment
Если директива using находится в sort_impl, вы должны указать istream и ostream в ее подписи. (Это не катастрофа, но предотвращение такого многословия - причина использования директивы using!) Вы также должны иметь по одной для каждой функции.   -  person Davis Herring    schedule 12.09.2017


Ответы (2)


Вы загрязняете свое собственное detail пространство имен, но не Lib или глобальные пространства имен. Итак, если вашей библиотекой пользуется ответственный взрослый, у него не будет непреднамеренных конфликтов имен:

#include <vector>

namespace Lib {
  namespace detail {
    using namespace std;
  }
}

using namespace Lib;

int main() {
    vector<int> v; // This is an error, vector not declared in this scope
}
person StoryTeller - Unslander Monica    schedule 12.09.2017
comment
Было бы рекомендовано здесь дополнительное анонимное пространство имен? - person Passer By; 12.09.2017
comment
@PasserBy - Нет. Если Lib объявлен в заголовке, я думаю, это может вызвать нарушения ODR для любого типа, объявленного внутри. Анонимные пространства имен различны в каждой единице перевода. - person StoryTeller - Unslander Monica; 12.09.2017
comment
+1 Это должен быть принятый ответ. Изоляция - это не защита от преднамеренного злоупотребления, а просто предоставление возможности пользователям, которые ведут себя, избежать нежелательных побочных эффектов. - person DrSvanHay; 12.09.2017

Нет, пространство имен detail не изолирует клиентов от вложенной директивы using. [namespace.udir] довольно четко об этом говорит.

using-directive. указывает, что имена в назначенном пространстве имен могут использоваться в области, в которой using-directive появляется после директива-using. Во время неквалифицированного поиска имени имена отображаются так, как если бы они были объявлены в ближайшее включающее пространство имен, которое содержит как using-директиву и назначенное пространство имен. [Примечание. В этом контексте «содержит» означает «прямо или косвенно содержит». - конец примечания]

Небольшой пример

#include <iostream>

namespace foo {
    namespace detail {
        using namespace std;
    }
}

int main()
{
    foo::detail::cout << "Hello World!\n";

    // nothing is stopping me from doing that
    using namespace foo::detail;
    cout << "Hello World!\n";
}

STL дает хорошее объяснение того, как работает поиск имени, в его видео Core C ++, 1 из n.

person Henri Menke    schedule 12.09.2017
comment
Весь смысл пространства имен detail состоит в том, чтобы поместить туда детали реализации. Ожидается, что разработчики будут взрослыми, а не просто вдаваться в детали. Работает в библиотеках как boost. Я думаю, вы неправильно поняли намерения ОП. Они хотят предотвратить случайное столкновение имен, а не клиенты, стреляющие себе в ногу. - person StoryTeller - Unslander Monica; 12.09.2017
comment
Я думаю, что OP спрашивает о случаях, не злоупотребляющих - person Passer By; 12.09.2017
comment
@StoryTeller »Сделайте интерфейсы удобными для правильного использования и трудными для неправильного использования.« (Скотт Мейерс) Если вы можете сделать using namespace detail;, кто-то это сделает. Следовательно, защитите всех, не имея using namespace объявлений в пространстве имен или глобальной области. - person Henri Menke; 12.09.2017
comment
@HenriMenke - Я согласен со Скоттом. Следовательно, пространство имен деталей не является частью интерфейса. Вы несколько искажаете то, что он сказал. Подход ответственного взрослого работает во многих библиотеках C ++, предназначенных только для заголовков. Я уже назвал boost, но вы должны посмотреть, что делают заголовки стандартных библиотек, если вы не уверены. - person StoryTeller - Unslander Monica; 12.09.2017
comment
Кроме того, это не значит, что ваш ответ неправильный, это (+1). На мой взгляд, это просто излишне осторожно. - person StoryTeller - Unslander Monica; 12.09.2017