【问题标题】:How to use boost::range::adaptors::transformed over std::unordered_set?如何在 std::unordered_set 上使用 boost::range::adaptors::transformed?
【发布时间】:2017-09-20 19:44:26
【问题描述】:

我正在尝试在 std::unordered_set 上使用 boost::adaptors::transformed 但即使在很小的实验中也似乎会产生奇怪的行为。

我在带有 gcc 5.4.0 的 Ubuntu 16.04 上使用 Boost 1.58.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'

谁能告诉我这个例子有什么问题?

【问题讨论】:

    标签: c++ c++11 boost boost-range


    【解决方案1】:

    transformed 不将范围的引用存储为范围;它在the range adaptor's construction 时抓取范围内的begin/end 迭代器。

    当您稍后在构建适配器之后插入到集合中时,新元素可能不在插入之前由旧的 begin/end 迭代器分隔的范围内。或者,更糟糕的是,如果插入触发了重新散列,则插入将使所有迭代器无效。

    【讨论】:

      【解决方案2】:

      我真的看不出问题:

      Your exact sample code(现场)打印:

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

      这似乎是您应该期待的。


      Using the other elements:

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

      想法:

      分配模板表达式可以是Undefined Behaviour

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

      因为double_int() 可能保留在transformed 适配器中通过引用(尚未检查)。

      看看这是否为您解决了问题:

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

      【讨论】:

      猜你喜欢
      • 2014-12-16
      • 1970-01-01
      • 2021-03-21
      • 2014-10-15
      • 1970-01-01
      • 2015-12-29
      • 1970-01-01
      • 1970-01-01
      • 2015-10-22
      相关资源
      最近更新 更多