Re[6]: портирование кода с MSVC на gcc
От: abrec Россия  
Дата: 19.08.09 17:11
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Здравствуйте, 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 == *it
К>        return;

К>    Set::iterator left, right; // можно обойтись вообще одним итератором (а при известной ловкости - даже только it)
    
К>    bool const left_ok  = (left=it)==cont.begin()  || cmp()(*(--left),value); // *left < value
К>    bool const right_ok = ++(right=it)==cont.end() || cmp()(value,*right);    // value < *right
К>    // для multiset нужно проверять !cmp(value,*left) и !cmp(*right,value),
К>    // т.е. *left <= value и value <= *right
    
К>    if(left_ok && right_ok)
К>        const_cast<Set::key_type&>(*it) = value; // хак
К>    else // тормоза, зато честно
К>    {
К>        cont.erase(it);
К>        cont.insert(value);
К>    }
К>}
К>


Спасибо!
В принципе там в сет

//Предикат для сравнения двух ключей
    struct Less
    {
        bool operator()(
                const CINIItem &l, 
                const CINIItem &r) const
        {         
            if(l.m_strSectionName == r.m_strSectionName)
                return l.m_strValueName < r.m_strValueName;
            else
                return l.m_strSectionName < r.m_strSectionName;
        };
    };

так что изменение value не имеет значения
Re[7]: портирование кода с MSVC на gcc
От: Кодт Россия  
Дата: 19.08.09 18:25
Оценка: 2 (1)
Здравствуйте, abrec, Вы писали:

A> так что изменение value не имеет значения


Почему бы сразу не сделать map< pair<string,string>, string >
где ключ — это пара (секция,имя), а значение — это, собственно, значение?

Вместо стандартной пары можешь написать собственный класс CINIKey... Хотя это незачем, т.к. над pair<...> уже определены все нужные операторы.

Это и идеологически верно, и итерировать позволяет по-прежнему (элементы мапа — map<K,V>::value_type — pair<const K,V>).
... << RSDN@Home 1.2.0 alpha 4 rev. 1237>>
Перекуём баги на фичи!
Re[3]: портирование кода с MSVC на gcc
От: Юрий Жмеренецкий ICQ 380412032
Дата: 19.08.09 19:10
Оценка: 60 (1)
Здравствуйте, Кодт, Вы писали:

К>Здравствуйте, Юрий Жмеренецкий, Вы писали:


ЮЖ>>Это "правильная" ошибка, в MSVC баг связанный с багом в стандарте: разрешено вызвать неконстантные методы для результата разыменования итераторов std::set, хотя по логике ключи иммутабельны. Для изменения значения ключа нужно удалить элемент со старым значением и вставить с измененным.


К>То есть, value_type — не typedef const key_type, а просто key_type ?!

К>(По аналогии с map — typedef pair<const key_type,mapped_type> value_type)

К>Полез в Стандарт изумляться...


В C++ Standard Library Defect Report List есть подробное описание дефекта. Примечательно то, что исправление достаточно хитрое и затрагивает все ассоциативные контейнеры:

103. set::iterator is required to be modifiable, but this allows modification of keys

...
23.1 [container.requirements] actually requires that iterator type pointing to T (table 65). Disallowing user modification of keys by changing the standard to require an iterator for associative container to be the same as const_iterator would be overkill since that will unnecessarily significantly restrict the usage of associative container. A class to be used as elements of set, for example, can no longer be modified easily without either redesigning the class (using mutable on fields that have nothing to do with ordering), or using const_cast, which defeats requiring iterator to be const_iterator. The proposed solution goes in line with trusting user knows what he is doing.
...
Proposed resolution:

Add the following to 23.1.4 [associative.reqmts] at the indicated location:

At the end of paragraph 3: "For any two keys k1 and k2 in the same container, calling comp(k1, k2) shall always return the same value."

At the end of paragraph 5: "Keys in an associative container are immutable."

At the end of paragraph 6: "For associative containers where the value type is the same as the key type, both iterator and const_iterator are constant iterators. It is unspecified whether or not iterator and const_iterator are the same type."

Rationale:

Several arguments were advanced for and against allowing set elements to be mutable as long as the ordering was not effected. The argument which swayed the LWG was one of safety; if elements were mutable, there would be no compile-time way to detect of a simple user oversight which caused ordering to be modified. There was a report that this had actually happened in practice, and had been painful to diagnose. If users need to modify elements, it is possible to use mutable members or const_cast.

Re[8]: портирование кода с MSVC на gcc
От: abrec Россия  
Дата: 20.08.09 03:46
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Здравствуйте, abrec, Вы писали:


A>> так что изменение value не имеет значения


К>Почему бы сразу не сделать map< pair<string,string>, string >

К>где ключ — это пара (секция,имя), а значение — это, собственно, значение?

К>Вместо стандартной пары можешь написать собственный класс CINIKey... Хотя это незачем, т.к. над pair<...> уже определены все нужные операторы.


К>Это и идеологически верно, и итерировать позволяет по-прежнему (элементы мапа — map<K,V>::value_type — pair<const K,V>).


Спасибо. Недотумкал как то.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.