代码在VS2008中编译,但在VS2010中没有用于std :: set和boost :: trim

时间:2011-06-08 22:09:31

标签: visual-studio-2010 boost stl

以下代码

#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迭代器。如果这是预期的行为,为什么有人有任何想法?

2 个答案:

答案 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通过不允许就地修改来解决问题(并符合新的标准草案)。

治疗方法是从装置中取出物品,根据需要进行修改,然后将其重新插入装置中(或者,如你所做的那样,抛弃常数,并祈祷你没有任何螺钉订购)。