以下代码
#include "stdafx.h"
#include <string>
#include <set>
#include <boost/algorithm/string/trim.hpp>
int _tmain(int argc, _TCHAR* argv[])
{
std::set<std::string> test;
test.insert("test1 ");
test.insert("test2 ");
for(std::set<std::string>::iterator iter = test.begin(); iter != test.end(); ++iter)
{
boost::algorithm::trim(*iter);
}
return 0;
}
在VS2008中编译但在VS2010中失败并出现错误
error C2663: 'std::basic_string<_Elem,_Traits,_Ax>::erase' : 3 overloads have no legal conversion for 'this' pointer \boost\include\boost\algorithm\string\trim.hpp
表示函数中的const匹配存在问题。如果我将set更改为vector,一切都很好。我也可以做一个
boost::algorithm::trim(const_cast<std::string&>(*iter));
但我讨厌把它放在我的代码中,似乎我不应该这样,因为我没有在集合上使用const迭代器。如果这是预期的行为,为什么有人有任何想法?
答案 0 :(得分:5)
std :: set的元素是不可变的。如果你可以在适当的位置更新它们,那么每当你更新一个元素(这将是非常困难,可能不可能实现)时,它要么需要重新排序,或者更新元素会破坏集合的排序保证。
允许集合的元素是可变的是原始C ++ 98标准中的疏忽。它在C ++ 11中得到了纠正;新标准要求设置迭代器以取消引用const元素。 VS10实现了新规则; VS08遵循旧标准,其中更新set元素会调用未定义的行为。
(参见final draft C++11 standard,第23.2.4节第6段。)
答案 1 :(得分:2)
是的,这是预期的行为。即使您不使用const_iterator,通常也需要将集合的内容视为const
。即使修改你制作(可能)不应该导致问题,通常修改它们可能需要更改元素的顺序以保持set的不变量,即项目始终按顺序排列
为了确保它们保持有序,您根本不能修改它们。
VS 2008允许这样做,但可能不应该(如:标准允许它,但它绝对不是一个好主意)。 VS 2010通过不允许就地修改来解决问题(并符合新的标准草案)。
治疗方法是从装置中取出物品,根据需要进行修改,然后将其重新插入装置中(或者,如你所做的那样,抛弃常数,并祈祷你没有任何螺钉订购)。