Я заменяю использование std::map
по горячей линии с cpp-btree's btree_map
. Но при включенной оптимизации GCC и Clang жалуются на строгое нарушение псевдонимов. Проблема сводится к следующему:Как я могу избежать расточительного копирования ключей на основе STL-подобной карты на основе B-дерева?
template <typename Key, typename Value>
class btree_map {
public:
// In order to match the standard library's container interfaces
using value_type = std::pair<const Key, Value>;
private:
using mutable_value_type = std::pair<Key, Value>;
struct node_type {
mutable_value_type values[N];
// ...
};
public:
class iterator {
// ...
value_type& operator*() {
// Here we cast from const std::pair<Key, Value>&
// to const std::pair<const Key, Value>&
return reinterpret_cast<value_type&>(node->values[i]);
}
};
std::pair<iterator, bool> insert(const value_type& value) {
// ...
// At this point, we have to insert into the middle of a node.
// Here we rely on nodes containing mutable_value_type, because
// value_type isn't assignable due to the const Key member
std::move_backward(node->values + i, node->values + j,
node->values + j + 1);
node->values[i] = value;
// ...
}
};
Это заставило меня задуматься, есть ли способ сделать это так же эффективно, что не опирается на неопределенное поведение? Ключи, которые я использую, эффективно перемещаются, но довольно медленно копируются, поэтому я бы хотел избежать копирования многих ключей при каждой вставке. Я рассмотрел
- Использование
value_type values[N]
, затемconst_cast<Key&>(values[i].first) = std::move(key)
переместить ключ вокруг, но я уверен, что до сих пор не определено - Возвращение
std::pair<const Key&, Value&>
вместоstd::pair<const Key, Value>&
когда это уместно, но я не уверен, что это будет по-прежнему удовлетворяют требованиям к контейнеру (я слышу, что...::reference
должен быть ссылочным типом) - Не заботясь. Код работает как есть, но мне любопытно, можно ли это сделать стандартным образом. Также есть вероятность, что будущие компиляторы будут делать разные вещи с UB, и я не знаю, как применить
-fno-strict-aliasing
только к одному классу.
Любые другие идеи?
Gcc предоставляет атрибут [may_alias] (http://stackoverflow.com/questions/6313050/gcc-how-to-use-attribute-may-alias-properly-to-avoid-derefencing-type), это работает как -fno-strict-aliasing, но только в выражениях, связанных с конкретной переменной (-ами) с атрибутом may_alias. –
Правда. (Вы имеете в виду 'may_alias'?) Интересно, есть ли способ сделать это без расширения langauge. –
Вы должны использовать ad-hoc C-массив? и вы должны использовать массив объектов или вы можете использовать массив указателей? –