如何使用boost :: range :: apapters ::通过std :: unordered_set转换

How to use boost::range::adaptors::transformed over std::unordered_set?

本文关键字:unordered set 转换 std apapters 何使用 boost range 通过      更新时间:2023-10-16

我正在尝试使用boost :: apapters ::通过std :: unordered_set进行转换,但似乎甚至在很小的实验上也会产生怪异的行为。

我在Ubuntu上使用Boost 1.58.0,使用GCC 5.4.0。

在迭代范围时未列出范围初始化后添加的元素:

#include <iostream>
#include <vector>
#include <unordered_set>
#include <boost/range/adaptor/transformed.hpp>
struct double_int
{
    typedef int result_type;
    int operator()(int x) const { return x * 2; }
};
int main()
{
  std::unordered_set<int> set;
  for(int i = 0; i < 5; ++i)
    set.insert(i); //adding ints to set
  auto range = set | boost::adaptors::transformed(double_int());
  set.insert(10); //adding some other int
  //this produces: '8 0 2 4 6'
  for(auto i : range)
    std::cout << i << std::endl;
  //this produces: '10 4 0 1 2 3'
  for(auto i : set)
    std::cout << i << std::endl;
  //element 10 is not doubled!
  return 0;
}

遵循其他STD容器(例如STD :: list)按预期工作,将后者添加的元素加倍。

加倍。

如果使用:

初始化集合,则更奇怪
std::unordered_set<int> set = {0,1,2,3,4,5};

范围迭代仅给出" 10",而容器的'10 0 1 2 3 4 5'

有人可以告诉我这个示例怎么了?

transformed不存储对该范围作为范围的引用;它抓住范围适配器构造时范围的begin/end迭代器。

当您在构造适配器后稍后将其插入集合时,新元素可能不在插入之前由旧的begin/end迭代器界定的范围内。或者,更糟糕的是,如果插入触发重新启动,插入将使所有迭代器无效。

我真的看不到问题:

您的确切示例代码(实时)打印:

8 20 6 4 0 2 
4 10 3 2 0 1 

这似乎是您应该期望的。


使用其他元素:

10 8 6 4 2 0 
5 4 3 2 1 0 

想法:

分配模板表达式可能是未定义的行为:

auto range = set | boost::adaptors::transformed(double_int());

因为double_int()可以通过参考保存在transformed适配器(尚未检查)。

查看这是否为您消除了问题:

for (auto i : set | boost::adaptors::transformed(double_int()))
    std::cout << i << " ";