Код компилируется в VS2008, но не в VS2010 для std :: set с boost :: trim - PullRequest
1 голос
/ 09 июня 2011

следующий код

#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  

, что указывает на проблему с сопоставлением констант в функциях. Если я изменю значение вектора, все будет в порядке. Я также могу сделать

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

но я ненавижу вставлять это в мой код, и мне кажется, что мне это не нужно, поскольку я не использую константный итератор на множестве. У кого-нибудь есть идеи, если это предполагаемое поведение и почему?

Ответы [ 2 ]

5 голосов
/ 09 июня 2011

Элементы std :: set предназначены для неизменности. Если бы вы могли обновить их на месте, это потребовало бы, чтобы набор был переупорядочен всякий раз, когда вы обновляли элемент (что было бы очень сложно, возможно, невозможно реализовать), или обновление элемента нарушило бы гарантию упорядочения набора.

Разрешение изменчивости элементов набора было упущением в исходном стандарте C ++ 98. Это было исправлено в C ++ 11; новый стандарт требует, чтобы итераторы набора обращались к элементу const. VS10 реализует новое правило; VS08 следовал старому стандарту, где обновление элемента set на месте вызывает неопределенное поведение.

(См. окончательный вариант стандарта C ++ 11 , раздел 23.2.4, пункт 6).

2 голосов
/ 09 июня 2011

Да, это предполагаемое поведение. Даже если вы не используете const_iterator, вам обычно нужно обрабатывать содержимое набора как const. Даже если модификация , которую вы делаете (вероятно), не должна вызывать проблем, для их изменения в общем случае может потребоваться изменить порядок элементов, чтобы сохранить инвариант набора, чтобы элементы всегда были в порядке.

Чтобы они оставались в порядке, вам не разрешается изменять их вообще.

VS 2008 позволил это, но, вероятно, не должен был (как в: стандартном виде позволил, но это определенно не было хорошей идеей). VS 2010 решает проблему (и соответствует новому проекту стандарта), не допуская изменения на месте.

Лекарство заключается в том, чтобы удалить предмет из набора, изменить по необходимости, а затем снова вставить его в набор (или, как вы сделали, выбросить постоянство и молиться, чтобы вы ничего не делали винтами до заказа).

...