名称查找和运算符重载如何工作?
How do name-lookup and operator-overload work?
我想输出一些私有库 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
}
在你里面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
的范围,不适用于 "propagate"(对 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<<
没有被考虑,你没有有效匹配,所以编译错误。
我想输出一些私有库 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
}
在你里面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
的范围,不适用于 "propagate"(对 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<<
没有被考虑,你没有有效匹配,所以编译错误。