Как работают поиск по имени и перегрузка оператора? - PullRequest
0 голосов
/ 12 июня 2018

Я хочу вывести некоторую личную библиотеку class ns::A в plog, поэтому я добавляю перегрузку operator << в ns::A.

Следующий код не может быть скомпилирован.

error: no match for ‘operator<<’ (operand types are ‘std::ostringstream’ {aka ‘std::__cxx11::basic_ostringstream<char>’} and ‘const ns::A’)
     out << t;
     ~~~~^~~~

Но изменение пространства имен other на ns, plog, plog::detail или std может привести к исчезновению ошибки компиляции, почему?std::cout<< и std::ostringstream<< в любом случае работают нормально.

#include <iostream>
#include <sstream>

namespace plog {
namespace detail {}
struct Record {
  template <typename T>
  Record& operator<<(const T& t) {
    using namespace plog::detail;

    out << t;
    return *this;
  }
  std::ostringstream out;
};
}

namespace ns {
struct A {};
}

namespace other {}

namespace other { // changing other to ns, plog, plog::detail or std will fix compiling error
inline std::ostream& operator<<(std::ostream& os, const ns::A& a) { return os; }
}

int main() {
  ns::A a;
  using namespace plog;
  using namespace plog::detail;
  using namespace ns;
  using namespace other;
  std::cout << a;
  std::ostringstream oss;
  oss << a;
  plog::Record s;
  s << a; // compiling error
}

1 Ответ

0 голосов
/ 12 июня 2018

В вас main:

int main() {
  ns::A a;
  using namespace plog;
  using namespace plog::detail;
  using namespace ns;
  using namespace other;
  std::cout << a;
  std::ostringstream oss;
  oss << a;
  plog::Record s;
  s << a; // compiling error
}

Ваш using namespace относится только к области действия main и не "распространяется" (до plog::Record::operator<< (const T& t)).

Тогда s << a; будет звонить plog::Record::operator<< (const T& t) с T = ns::A.

Итак, в

Record& operator<<(const T& t)
{
    using namespace plog::detail;

    out << t;
    return *this;
}

out << t;T = ns::A)будет смотреть на пространство имен (с ADL):

  • глобальное пространство имен
  • пространство имен plog (plog::Record)
  • пространство имен plog::detail (using namespace plog::detail;)
  • пространство имен std (std::ostringstream out)
  • пространство имен ns (ns::A)

other::operator<< не рассматривается, и вы нене найдено правильное совпадение, поэтому ошибка компиляции.

...