2013-12-16 3 views
2

Я хочу использовать карту STL с логически постоянными ключами (и мой код с использованием карты гарантирует никогда не нарушающий порядок клавиш), но фактически реализованный как переменная. Например,Tweaking const map key

struct K { int ka, kb; }; 

struct my_less : std::less<K> { 
    bool operator()(const K& l, const K& r) const 
     { return l.ka+l.kb < r.ka+r.kb; } 
}; 

std::map<K, int, my_less> m; 

// put something into m and now modify keys 

K& k = *const_cast<K *>(&m.begin()->first); 
k.ka++; 
k.kb--; // I skip code for verifying logical key immutability for the sake of example simplification 

Это работает (заказ карты не нарушен), но выглядит уродливым. Есть ли лучшие альтернативы?

Возможна дополнительная косвенность с указателем (указатель const const без создания данных const), но он несет накладные расходы (и добавляет излишнюю сложность).

Перемещение переменной ключевой части из ключа в значение не является для меня вариантом.

ответ

0

boost :: multi_index является разумной альтернативой для этого случая. Он поддерживает изменения, сохраняющие порядок, без больших накладных расходов.

1

Существует веская причина, по которой вы не можете аккуратно редактировать ключи карты - вы действительно не должны этого делать! В вашем случае может показаться, что не нарушить порядок карт, но это не гарантируется! (Подумайте, что произойдет, если вы измените два ключа, чтобы иметь одинаковые значения ka и kb?)

Правильный способ сделать это - удалить элемент с карты и снова вставить его с помощью нового ключа.

std::map<K, int, my_less> m; 

// Push our starting object into the map 
K key; 
key.ka = 42; 
key.kb = 123; 

m[key] = 1234; 

// Get the first element 
auto iter = m.begin(); 

// make a new key 
K key2; 
key2 = iter->first; 
key2.ka++; 
key2.kb--; 

int value = iter->second; 

// remove old value 
m.erase(iter); 

// insert new value 
m[key2] = value; 
+0

Да, это правильный путь, но он добавляет существенные накладные расходы, неприемлемые в моем случае. – byly

+0

По существенным накладным расходам, вы имеете в виду, что ваше значение представляет собой сложный объект, который хранится по значению на карте, поэтому копируется при вставке? Переход к значению интеллектуального указателя уменьшил бы это, поскольку вы только удаляли бы и вставляли бы указатель и не должны дублировать свой объект значения. – benjymous

+0

Нет, вставка/удаление дерева сама по себе не такая дешевая. Я добавил разъяснение к исходному вопросу: постоянный порядок ключей гарантируется кодом пользователя. – byly