[英]C++ set iterator error: no match for ‘operator+=’
I am trying to iterate over a set of objects and create a comma-separated string of their names. 我正在尝试遍历一组对象并创建它们名称的逗号分隔字符串。 The commented-out part of the code is supposed to add a comma only if it is not the last one in the set, but it generates the following error:
仅在代码注释掉的部分不是集合中的最后一个时,才应添加逗号,但是会产生以下错误:
error: no match for 'operator+=' (operand types are 'std::_Rb_tree_const_iterator' and 'long int') _M_current += -__n; 错误:与'operator + ='不匹配(操作数类型为'std :: _ Rb_tree_const_iterator'和'long int')_M_current + = -__ n;
It works fine if I use a vector instead of a set. 如果我使用向量而不是集合,则效果很好。 What am I doing wrong?
我究竟做错了什么?
std::string paramList = "";
std::set<Param>::iterator end = params.end();
for (std::set<Param>::iterator it = params.begin(); it != end; ++it) {
paramList += (*it).name;
/*if (it != end -1) {
paramList += ",";
}*/
}
Only certain categories of iterator allow you to directly perform arbitrary arithmetic, like end-1
. 仅某些迭代器类别允许您直接执行任意算术,例如
end-1
。
The iterator of a set permits going forwards and backwards one step at a time, using it++
and it--
. 集合的迭代器允许每次使用
it++
和it--
向前和向后前进一个步骤。 It is true that it - 1
still only traverses one step, but the rule is more general (the language doesn't know that the integer you're providing is just 1
and has no reason to make a special case compared to, say, 42
). 的确如此
it - 1
仍然只遍历一个步骤,但是规则却更笼统(语言不知道您提供的整数仅为1
, it - 1
相比,没有理由做特殊情况) 42
)。
It is possible to use std::next
/ std::prev
to get this behaviour. 可以使用
std::next
/ std::prev
获得此行为。 This is deliberately more verbose, in order to discourage you from arbitrary arithmetic on the iterator, which is more costly for this kind of iterator than it would be for a simple array-like thing such as a vector. 为了使您避免使用迭代器上的任意算术,这故意更冗长,与使用简单的类似数组的对象(例如矢量)相比,这种迭代器的开销更大。
In this case, std::prev(end)
will work for you, and be reasonably idiomatic. 在这种情况下,
std::prev(end)
将为您工作,并且是习惯用法。
But, if you find yourself writing something like std::next(it, 42)
, you probably want to consider improving your algorithm, or using a different container. 但是,如果您发现自己编写了类似
std::next(it, 42)
,则可能要考虑改进算法或使用其他容器。
Again, the purpose of this restriction is to encourage exactly that thinking. 同样,这种限制的目的是鼓励这种思维。
Another way to write your algorithm might be: 编写算法的另一种方法可能是:
std::string paramList;
std::set<Param>::iterator begin = params.begin(), end = params.end();
for (std::set<Param>::iterator it = begin; it != end; ++it) {
if (it != begin)
paramList += ",";
paramList += (*it).name;
}
Notice how I've flipped the logic to avoid the need to do any arithmetic at all. 请注意,我是如何翻转逻辑的,以免完全不需要做任何算术运算。
I actually usually use a bool
flag for this (when my paramList
is a stringstream) or just always append a ,
then shrink paramList
by one later (when it's a string) if params
was non-empty. 实际上,我通常为此使用
bool
标志(当我的paramList
是stringstream时),或者总是总是附加a ,
然后如果params
非空,
则将paramList
缩小一个(当它是字符串时)。
end -1
This part is causing the problem. 这是造成问题的原因。
std::set
only has Bidirectional iterators , so it only accepts operator ++
and operator --
on it. std::set
仅具有双向迭代器 ,因此它仅接受operator ++
和operator --
。
You should use std::prev
form <iterator>
header instead: 您应该使用
std::prev
form <iterator>
标头代替:
if (it != std::prev(end))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.