Что автор пытается сказать в GotW #53?

Этот псевдокод был получен из GotW #53 под подзаголовком "Не очень хорошее долгосрочное решение". Я уже несколько часов пытаюсь понять, что говорит автор, особенно в отношении комментария, начинающегося с "// error: потенциал..." ниже, но безрезультатно. Я был бы очень признателен за помощь в этом.

    //  Example 2c: Bad long-term solution (or, Why to
    //              avoid using declarations in
    //              headers, even not at file scope)
    //
    //--- file x.h ---
    //
    #include "y.h"  // declares MyProject::Y and adds
                    //  using declarations/directives
                    //  in namespace MyProject
    #include <deque>
    #include <iosfwd>
    namespace MyProject
    {
      using std::deque;
      using std::ostream;
      // or, "using namespace std;"
      ostream& operator<<( ostream&, const Y& );
      int f( const deque<int>& );
    }
    //--- file x.cpp ---
    //
    #include "x.h"
    #include "z.h"  // declares MyProject::Z and adds
                    //  using declarations/directives
                    //  in namespace MyProject
      // error: potential future name ambiguities in
      //        z.h's declarations, depending on what
      //        using declarations exist in headers
      //        that happen to be #included before z.h
      //        in any given module (in this case,
      //        x.h or y.h may cause potential changes
      //        in meaning)
    #include <ostream>
    namespace MyProject
    {
      ostream& operator<<( ostream& o, const Y& y )
      {
        // ... uses Z in the implementation ...
        return o;
      }
      int f( const deque<int>& d )
      {
        // ...
      }
    }

2 ответа

Его говорит не использовать using директива в заголовочном файле. Например: предположим, что у нас было 2 файла xh и zh с этими объявлениями:

// x.h
namespace MyProject
{
  using std::deque;
  using std::ostream;
  ....
};

// z.h
namespace MyProject
{
  using mystd::deque;
  using mystd::ostream;
  ....
};

Вопрос в том, какой объект ostream будет вызываться в вашем примере?

// x.cpp
#include "x.h"
#include "z.h"
#include <ostream>
namespace MyProject
{
  ostream& operator<<( ostream& o, const Y& y )
  {
    // ... uses Z in the implementation ...
    return o;
  }
  int f( const deque<int>& d )
  {
    // ...
  }
}

Вы хотели бы позвонить x.h определения, но из-за порядка включает в себя, он будет вызывать z.h включает в себя определения

Автор говорит, что проблема с этим кодом заключается в том, что, поскольку этот код используется в других приложениях, может быть несколько вещей с одним и тем же именем ("потенциальные будущие неоднозначности пространства имен"), в зависимости от того, какие пространства имен используются в других заголовочных файлах. Если они говорят, что следует использовать другое пространство имен, одно и то же имя может не указывать на то, что изначально задумал автор.

Другие вопросы по тегам