您收到此错误是因为您的函数将每次调用 << 与左侧的 std::ostream& 匹配。
template <typename C>
std::ostream& operator<<(std::ostream& os, const C& c) {
os << "[";
for (const auto& v : c) {
os << v << " ";
}
os << "]";
return os;
}
当你写os << "["时,编译器会找到多个operator<<函数来调用;你的就是其中之一。通过添加一个全局operator<<,它被模板化为任何类型,你基本上拦截了对operator<<的每个调用。
最简洁的方法是定义一个新函数,比如print_collection:
template <typename C>
void print_collection(std::ostream& os, const C& c) {
os << "[";
for (const auto& v : c) {
os << v << " ";
}
os << "]";
}
如果您真的想要定义operator<<,这会变得更加棘手。你可以这样做:
template <typename C>
std::ostream& operator<<(std::ostream& os, const std::vector<C>& c) {
os << "[";
for (const auto& v : c) {
os << v << " ";
}
os << "]";
return os;
}
但是,如果标准库决定为std::vector 添加自己的operator<<,您的代码将会中断。
我强烈建议,如果您想添加这样的operator<<,请为您自己的类型添加。像这样的:
template <typename Iter>
class Range {
Iter begin_;
Iter end_;
public:
Range() = default;
Range(Iter begin, Iter end)
: begin_{ begin }
, end_{ end }
{}
auto begin() const { return begin_; }
auto end() const { return end_; }
};
template <typename Iter>
auto range(Iter begin, Iter end) {
return Range<Iter>{ begin, end };
}
template <typename C>
auto range(const C& collection) {
return range(std::begin(collection), std::end(collection));
}
template <typename Iter>
std::ostream& operator<<(std::ostream& os, const Range<Iter>& range) {
os << "[";
for (const auto& v : range) {
os << v << " ";
}
os << "]";
return os;
}
那么你可以这样使用它:
std::vector<int> vec = ...;
std::cout << range(vec);