Я заменяю использование std::map
горячим путем cpp-btree btree_map
. Но при включенной оптимизации GCC и Clang жалуются на строгое нарушение псевдонимов. Проблема сводится к следующему:
template <typename Key, typename Value>
class btree_map {
public:
// In order to match the standard library 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;
// ...
}
};
Это заставило меня думать, есть ли способ сделать это так эффективно, что не полагается на поведение undefined? Ключи, которые я использую, эффективно перемещаются, но довольно медленно копируются, поэтому я бы хотел избежать копирования многих ключей при каждой вставке. Я рассмотрел
- Используя
value_type values[N]
, затемconst_cast<Key&>(values[i].first) = std::move(key)
, чтобы переместить ключ, но я уверен, что все еще undefined - Возвращая
std::pair<const Key&, Value&>
вместоstd::pair<const Key, Value>&
, если это необходимо, но я не уверен, что это все равно будет удовлетворять требованиям контейнера (я слышу, что...::reference
должен быть ссылочным типом) - Не заботьтесь. Код работает как есть, но мне любопытно, можно ли это сделать стандартным образом. Также есть вероятность, что будущие компиляторы будут делать разные вещи с UB, и я не знаю, как применить
-fno-strict-aliasing
только к одному классу.
Любые другие идеи?