提问人:Joshua Jakowlew 提问时间:8/17/2023 最后编辑:Alan BirtlesJoshua Jakowlew 更新时间:8/17/2023 访问量:62
ostream 运算符<<从不同命名空间使用时解析失败
ostream operator<< resolution fails when used from different namespaces
问:
我在命名空间中为 for 进行了重载。
据我了解,ADL 不会隐式看到这个重载,因为不是 的成员,所以我们必须在调用代码时使用命名空间来查看这个重载。ostream operator<<
std::vector
printable
std::vector
printable
printable
在其他命名空间中,我为我的类定义了另一个重载。在那之后,代码中断并且无法编译。my::fails
foo
在命名空间中,我没有使用整个命名空间,只有 ,并且...一切都还好。为什么?有什么区别。my::suddenly_works
printable
operator<<
在那之后,我没有定义任何附加重载,而只是使用命名空间,使用重载运算符。一切都很好,正如预期的那样。my::works
printable
所以,问题是:如何正确地在命名空间中重载未在此命名空间中定义的类型,以及如何在调用端的另一个命名空间中使用这些重载。ostream operator<<
另外,作为一个附带问题,在给定的例子中和有什么区别?using namespace printable
using printable::operator<<
这是代码(godbolt 链接):
#include <iostream>
#include <vector>
namespace printable
{
template <typename T>
inline auto operator<<(std::ostream& os, std::vector<T> const & v) -> std::ostream &
{
os << '[';
for (auto it = v.cbegin(); it != v.cend() - 1; ++it)
{
os << *it << ", ";
}
os << v.back() << ']';
return os;
}
}
namespace my::fails
{
struct foo {};
inline auto operator<<(std::ostream& os, foo const & f) -> std::ostream &
{
std::vector v{1, 2, 3, 4, 5};
std::cout << v << '\n';
return os;
}
using namespace printable;
void print_vec()
{
std::vector v{1, 2, 3, 4, 5};
std::cout << v << '\n';
}
}
namespace my::suddenly_works
{
using printable::operator<<;
struct foo {};
inline auto operator<<(std::ostream& os, foo const & f) -> std::ostream &
{
std::vector v{1, 2, 3, 4, 5};
std::cout << v << '\n';
return os;
}
void print_vec()
{
std::vector v{1, 2, 3, 4, 5};
std::cout << v << '\n';
}
}
namespace my::works
{
using namespace printable;
void print_vec()
{
std::vector v{1, 2, 3, 4, 5};
std::cout << v << '\n';
}
}
int main()
{
using namespace printable;
std::vector v{1, 2, 3, 4, 5};
std::cout << v << '\n';
my::works::print_vec();
my::suddenly_works::print_vec();
my::fails::print_vec();
}
我试图了解 ADL 和过载解决方案的工作原理,但 bu 还不能将我的 have 包裹起来。另外,谷歌搜索什么也没给我。
答: 暂无答案
评论
using
operator<<