shift::bimap 中的值

Shift values in boost::bimap

提问人:Nikita Rudenko 提问时间:2/9/2020 最后编辑:Nikita Rudenko 更新时间:2/9/2020 访问量:127

问:

我有一个无序的双映射,如下所示:

using SymPressMap =
    boost::bimap<boost::bimaps::unordered_set_of<sym>,
                 boost::bimaps::unordered_set_of<Press>>;

这基本上是“sym”和“Press”之间的双射。我想循环“Presses”的子集,如图片所示:bimap 状态前后

以下是使用 std::unordered_map 编译但使用 bimap 失败的算法:

void Layout::cycle(SymVector syms) {
  assert(syms.size() >= 2);
  for (auto it = syms.rbegin(); it != syms.rend() - 1; it++) {
    std::swap(sympressmap.left.at(*it), sympressmap.left.at(*(it + 1)));
  }
}

其基本思想是连续交换相邻的(以“符号”为单位)元素。但是我收到此错误:

Error   C2678   binary '=': no operator found which takes a left-hand operand of type '_Ty' (or there is no acceptable conversion)  
KeyboardOptimizer   c:\program files (x86)\microsoft visual studio\2017\professional\vc\tools\msvc\14.16.27023\include\utility  68  

所以,问题是如何在 bimap 中交换两个元素?

UPD:擦除插入版本,感谢 John Zwinck,它编译

void Layout::cycle(SymVector syms) {
  assert(syms.size() >= 2);
  Press plast = pressmap.left.at(*syms.rbegin());
  pressmap.left.erase(*syms.rbegin());
  for (auto it = syms.rbegin() + 1; it != syms.rend(); it++) {
    auto p = pressmap.left.at(*it);
    pressmap.left.erase(*it);
    pressmap.left.insert(SymPressMap::left_value_type(*(it - 1), p));
  }
  pressmap.left.insert(SymPressMap::left_value_type(*syms.begin(), plast));
}
C++ C++14 提升 bimap

评论


答:

1赞 John Zwinck 2/9/2020 #1

使用常规unordered_map,交换值没有问题,因为容器结构不依赖于它们。但是,修改键是一个常见的困难和混乱领域,因为键定义了容器的结构(哪些值放在哪些存储桶中)。mapped_typekey_type

你在这里有同样的问题,那就是你试图修改存储在容器中的键(你是在交换值方面这样做的,但在双映射中,键和值当然是对偶的)。你不能这么做。您可以做的是复制键值对,交换其值,从容器中删除原始值对,然后插入修改后的键值对。

参考:如何更改unordered_map中的密钥?

评论

0赞 Nikita Rudenko 2/9/2020
谢谢。但是,如果无序双映射基于两个映射,则交换可以更有效:只需交换两个映射中的值
0赞 John Zwinck 2/10/2020
一个的value_type将是另一个的mapped_type,因此通常无法交换它们(在您的示例用例中也是如此)。
0赞 Nikita Rudenko 2/10/2020
当 bimap 基于两个映射时,无需移位键:在第一个映射值中顺时针移动,在第二个映射值中逆时针移动。因此,钥匙“停留”在它们的位置。