Здравствуйте!
Писал проект на MSVC с галочкой в мозге, что возможно надо будет портировать на linux. Сбылось.
Поставил openSUSE 11, codeblocks, boost_1_39_0.
Началось.... Нашел у себя несколько явных косяков
Помогите разобраться.
Здравствуйте, abrec, Вы писали:
A>Писал проект на MSVC с галочкой в мозге, что возможно надо будет портировать на linux. Сбылось. A>Поставил openSUSE 11, codeblocks, boost_1_39_0. A>Началось.... Нашел у себя несколько явных косяков A>Помогите разобраться. A>
A>//../Public/Include/inidata.h|165|ошибка: нет подходящей функции для вызова ‘CINIItem::SetValue(std::basic_string<char, std::char_traits<char>, std::allocator<char> >) const’|
A>//../Public/Include/inidata.h|50|замечание: претенденты: void CINIItem::SetValue(const std::string&) <near match>|
A>
Ну написано же — константность мешает. Почему VC разрешает изменять элемент множества через итератор и что при этом происходит с множеством и с итератором — хз.
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Здравствуйте, Sergey, Вы писали:
S>Здравствуйте, abrec, Вы писали:
A>>Писал проект на MSVC с галочкой в мозге, что возможно надо будет портировать на linux. Сбылось. A>>Поставил openSUSE 11, codeblocks, boost_1_39_0. A>>Началось.... Нашел у себя несколько явных косяков A>>Помогите разобраться. A>>
A>>//../Public/Include/inidata.h|165|ошибка: нет подходящей функции для вызова ‘CINIItem::SetValue(std::basic_string<char, std::char_traits<char>, std::allocator<char> >) const’|
A>>//../Public/Include/inidata.h|50|замечание: претенденты: void CINIItem::SetValue(const std::string&) <near match>|
A>>
S>Ну написано же — константность мешает. Почему VC разрешает изменять элемент множества через итератор и что при этом происходит с множеством и с итератором — хз.
Здравствуйте, Sni4ok, Вы писали:
S>Здравствуйте, abrec, Вы писали:
S>бага msvc- что скомпилила, по итератеру сета нельзя менять значение, ибо сет может стать невалидным.
тобишь надо взять элемент изменить и обратно в сет засунуть?
Здравствуйте, abrec, Вы писали:
A>так вроде есть отдельный const_iterator.???
константый итератор нельзя удалить, неконстантный можно, чтобы поменять значение в set'е- сначала удалите по итератеру, и потом добавте новое значение.
Здравствуйте, Sni4ok, Вы писали:
S>Здравствуйте, abrec, Вы писали:
A>>так вроде есть отдельный const_iterator.???
S>константый итератор нельзя удалить, неконстантный можно, чтобы поменять значение в set'е- сначала удалите по итератеру, и потом добавте новое значение.
в принципе логично. ведь он там пересортировывается постоянно. как же vc пропустила?
Здравствуйте, abrec, Вы писали:
A>Здравствуйте! A>Писал проект на MSVC с галочкой в мозге, что возможно надо будет портировать на linux. Сбылось. A>Поставил openSUSE 11, codeblocks, boost_1_39_0. A>Началось.... Нашел у себя несколько явных косяков A>Помогите разобраться. A>
A>class CINIItem
A>{
A>private:
A> std::string m_strSectionName;
A> std::string m_strValueName;
A> std::string m_strValue;
A>public:
A> CINIItem(const char* pszSectionName, const char* pszValueName, const char* pszValue);
A> ...
A> const std::string& GetValue()const { return m_strValue; } ;
A> void SetValue(const std::string& strNewValue) { m_strValue = strNewValue; };
A> ...
A> typedef std::set< CINIItem, CINIItem::Less > INIITEMS;
A>};
A>class CINIData
A>{
A>protected:
A> CINIItem::INIITEMS m_INIItems;
A>public:
A> CINIData(){};
A> ...
A> bool SetValue(const char* pszSectionName, const char* pszValueName, const long& lValue)
A> {
A> CINIItem item(pszSectionName, pszValueName, "");
A> CINIItem::INIITEMS::iterator iter = m_INIItems.find(item);
A> if(iter == m_INIItems.end()) return false;
A> std::stringstream sValue;
A> sValue << lValue;
A> (*iter).SetValue(sValue.str());//здесь ошибка!!!!
A>//../Public/Include/inidata.h|165|ошибка: нет подходящей функции для вызова ‘CINIItem::SetValue(std::basic_string<char, std::char_traits<char>, std::allocator<char> >) const’|
A>//../Public/Include/inidata.h|50|замечание: претенденты: void CINIItem::SetValue(const std::string&) <near match>|
A> return true;
A> };
A> ...
A>};
A>
Это "правильная" ошибка, в MSVC баг связанный с багом в стандарте: разрешено вызвать неконстантные методы для результата разыменования итераторов std::set, хотя по логике ключи иммутабельны. Для изменения значения ключа нужно удалить элемент со старым значением и вставить с измененным.
Здравствуйте, abrec, Вы писали:
A>тобишь надо взять элемент изменить и обратно в сет засунуть?
угу, но если вы уверены, что ваша неконстантная операция не может повлиять на сортировку(не изменяете полей от которых зависит компаратор), то лучше воспользоваться конст-кастом, поскольку удаление и обратная вставка- всётаки не дешёвая операция.
Здравствуйте, Sni4ok, Вы писали:
S>Здравствуйте, abrec, Вы писали:
A>>тобишь надо взять элемент изменить и обратно в сет засунуть?
S>угу, но если вы уверены, что ваша неконстантная операция не может повлиять на сортировку(не изменяете полей от которых зависит компаратор), то лучше воспользоваться конст-кастом, поскольку удаление и обратная вставка- всётаки не дешёвая операция.
спасибо const_cast ом вышел из ситуевины.
1. барьер пройден
Re[7]: портирование кода с MSVC на gcc
От:
Аноним
Дата:
19.08.09 16:16
Оценка:
извини, я разглядел наконец, что компилятор к другому совсем цеплялся.
Здравствуйте, Юрий Жмеренецкий, Вы писали:
ЮЖ>Это "правильная" ошибка, в MSVC баг связанный с багом в стандарте: разрешено вызвать неконстантные методы для результата разыменования итераторов std::set, хотя по логике ключи иммутабельны. Для изменения значения ключа нужно удалить элемент со старым значением и вставить с измененным.
То есть, value_type — не typedef const key_type, а просто key_type ?!
(По аналогии с map — typedef pair<const key_type,mapped_type> value_type)
Здравствуйте, abrec, Вы писали:
S>>угу, но если вы уверены, что ваша неконстантная операция не может повлиять на сортировку(не изменяете полей от которых зависит компаратор), то лучше воспользоваться конст-кастом, поскольку удаление и обратная вставка- всётаки не дешёвая операция. A>спасибо const_cast ом вышел из ситуевины. A>1. барьер пройден
Может, хотя бы проверку делать?
template<class Set>
void set_update(Set& cont, Set::iterator it, Set::value_type value)
{
Set::value_compare cmp = cont.value_comp();
if(!cmp(*it,value) && !cmp(value,*it)) // value == *itreturn;
Set::iterator left, right; // можно обойтись вообще одним итератором (а при известной ловкости - даже только it)bool const left_ok = (left=it)==cont.begin() || cmp()(*(--left),value); // *left < valuebool const right_ok = ++(right=it)==cont.end() || cmp()(value,*right); // value < *right
// для multiset нужно проверять !cmp(value,*left) и !cmp(*right,value),
// т.е. *left <= value и value <= *rightif(left_ok && right_ok)
const_cast<Set::key_type&>(*it) = value; // хакelse// тормоза, зато честно
{
cont.erase(it);
cont.insert(value);
}
}