Код компилируется в VS2008, но не в VS2010 для std::set с boost ::trim

#visual-studio-2010 #boost #stl

#visual-studio-2010 #повышение #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    boostincludeboostalgorithmstringtrim.hpp  
  

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

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

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

Комментарии:

1. Перед вставкой следует выполнить обрезку.

2. @dalle — Я согласен, но у меня нет полного контроля над этим кодом

Ответ №1:

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

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

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

Ответ №2:

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

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

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

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