如何使用<<运算符将元素添加到向量?

How to add an element to a vector by using the << operator?

本文关键字:lt 向量 添加 运算符 何使用 元素      更新时间:2023-10-16

举个例子,如果我想将元素"Hello""World"添加到名为vstd::vector<std::string>,我必须使用v.push_back("Hello")v.push_back("World")

取而代之的是,我想重载<<运算符,以便我可以这样做:

v << "Hello" << "World";

在我的头文件中,我有以下功能,但它不起作用:

ostream& operator<<(ostream& out, vector<string>& v) {
out << v;
}
v << "foo";

此处左操作数vector<string>,右操作数string。所以这应该有效:

vector<string>& operator<<(vector<string>& v, const string& s) {
v.push_back(s);
return v;
}

但在我看来,这将不太易读,也不是一个好主意。

首先是向前说一句话:向量不是流,我宁愿不建议这样做。但是如果你坚持:你必须让你的向量扮演通常流所扮演的角色,即:

std::vector<std::string>& operator<<(std::vector<std::string>& v, std::string s);

嗯,当然,在实现中,你会调用push_back,当然......在推回时使用std::move从移动语义中获利......

甚至可以将其制作为模板:

template <typename T, typename V>
std::vector<T>& operator<<(std::vector<T>& c, V v)
{
c.push_back(T(std::move(v)));
return c;
}

这将允许将任何数据类型添加到任意类型的向量中,只要向量的类型可以从给定的值构造......更好的是,自 C++11 以来:

c.emplace_back(std::move(v));
vector<string>& operator<<(vector<string> &a,const string &b)
{
a.push_back(b);
return a;
}

我同意@Caleth这个评论:

这是很有可能的,但这是一个坏主意,特别是如果人们 除此之外,您将像这样阅读您编写的代码。v.push_back("Hello")是标准的,所以很容易理解你 正在做。v << "Hello";会给人惊喜,惊喜对 理解。

因此,像其他好的答案建议一样简单地添加重载并不是我会做的事情。但是,我认为想要将内容"流式传输"到矢量中并没有什么固有的坏处。最好是明确一些事情,所以很明显我们正在使用自制的实用程序。因此,让我们添加一个间接级别:

template<typename T, typename A>
class vec_streamer {
std::vector<T, A>& target;
friend vec_streamer const& operator<<(vec_streamer const& self, T const& t) {
self.target.push_back(t); return self;
}
friend vec_streamer const& operator<<(vec_streamer const& self, T && t) {
self.target.push_back(std::move(t)); return self;
}
public:
vec_streamer(std::vector<T, A>& target)  : target(target) {}
};

上面是一个方便的实用程序,允许我们编写这个 c++17 代码(现场观看!

std::vector<int> v;
vec_streamer(v) << 1 << 2 << 3 << 4;

请注意vec_streamer(v)如何发送一个明确的信息,我们正在用这里的向量做一些事情(它依赖于模板参数推导,因此需要 C++17(。这样做的好处是,这个operator<<可以通过 ADL 找到(事实上,只有 ADL(,所以如果任何模板化代码使用operator<<我们可以传入vec_streamer(v)并获得预期的行为。接受向量作为左参数的朴素重载不会从中受益。