开发者

Code compiles in VS2008 but not in VS2010 for std::set with boost::trim

The following code

#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(); ++it开发者_高级运维er)
    {
        boost::algorithm::trim(*iter);
    }

    return 0;
}

compiles in VS2008 but fails in VS2010 with the error

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  

which indicates there is a problem with const matching in the functions. If I change set to vector everything is fine. I can also do a

boost::algorithm::trim(const_cast<std::string&>(*iter));

but I hate putting that in my code, and it seems like I shouldn't have to as I'm not using a const iterator on the set. Does anyone have any ideas if this is the intended behavior and why?


The elements of a std::set are intended to be immutable. If you could update them in place, it would either require the set to be re-ordered whenever you updated an element (which would be very hard, possibly impossible, to implement), or updating an element would break the set's guarantee of ordering.

Allowing the elements of a set to be mutable was an oversight in the original C++98 standard. It was corrected in C++11; the new standard requires set iterators to dereference to a const element. VS10 implements the new rule; VS08 followed the old standard, where updating a set element in place invokes undefined behaviour.

(See the final draft C++11 standard, section 23.2.4 para 6.)


Yes, it's intended behavior. Even when you don't use a const_iterator, you normally need to treat the contents of a set as const. Even though the modification you're making (probably) shouldn't cause a problem, modifying them in general could require that the order of the elements be changed to maintain set's invariant that the items are always in order.

To ensure that they stay in order, you aren't allowed to modify them at all.

VS 2008 allowed this, but probably shouldn't have (as in: the standard sort of allowed it, but it definitely wasn't a good idea). VS 2010 fixes the problem (and conforms with the new draft standard) by not allowing in-place modification.

The cure is to remove the item from the set, modify as needed, and then re-insert it into the set (or, as you've done, cast away the const-ness, and pray that nothing you do screws up the ordering).

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜