【问题标题】:advance the iterator of a standard map推进标准地图的迭代器
【发布时间】:2014-03-04 17:45:16
【问题描述】:

主要问题已经在标题中了:如何推进标准地图的迭代器?

但由于大多数人问我为什么需要这个,我将提供更多信息: 我有一堂有几张地图的课。我至少有 2 个微分方程、至少 2 种传感器类型(场或 dft)和至少 2 种空间类型(体积、表面)。我需要保存所有这些东西,并在它们之间建立关联。 所以我认为拥有这些事物的映射是明智的,当事物相互关联时,它们在映射中具有相同的键。

为简单起见,我们只考虑三个地图。

class Reader
{
    struct MaxwellSensor
    {
        // some members...
    };
    struct FieldSensor
    {
        // some members
        uint fieldMember;
    };
    struct DFTSensor
    {
        // some members
        uint dftMember;
    };    
    std::map<uint, MaxwellSensor> maxwellSensors;
    std::map<uint, FieldSensor> fieldSensors;
    std::map<uint, DFTSensor> dftSensors;

    uint getCountOfMaxwellSensors(){
        return maxwellSensors.size();
    }

    uint getMemberForMaxwellSensorByIndex(uint index){
        // This follows later
    }

};

在我的程序过程中,我需要实例化 SensorInterface 的几个变量。 为此,我需要知道我有多少个麦克斯韦传感器,然后遍历麦克斯韦传感器并获取其他传感器的成员。

这看起来像:

class MyType{
    public:
        uint member;
}

int main(int argc, const char* argv[])
{
    // some code
    Reader myReader;
    for(uint i = 0; i < myReader.countOfMaxwellSensors(); ++i)
    {
        MyType var;
        var.member = myReader.getMemberForMaxwellSensorByIndex(i);
    }
}

所以阅读器中的函数应该是这样的:

uint getMemberForMaxwellSensorByIndex(uint index)
{
    auto maxIt = std::advance(maxwellSensors.begin(), index);
    auto foundInFieldSensorsIt = std::find_if(fieldSensors.begin(), fieldSensors.end(), [&] (const std::pair<UInteger_T, FieldSensor>& kvp) { return kvp.first == maxIt->first; });
    auto foundInDFTSensorsIt = std::find_if(dftSensors.begin(), dftSensors.end(), [&] (const std::pair<UInteger_T, DFTSensor>& kvp) { return kvp.first == maxIt->first; });
    if(foundInFieldSensorsIt != fieldSensors.end())
        return fieldSensors[maxIt->first].fieldMember;
    else if(foundInDFTSensorsIt != dftSensors.end())
        return dftSensors[maxIt->first].fieldMember;
    else
    {
        std::cerr << "something went wrong." << std::endl;
        return 0;
    }
}

所以...这是std::advance(maxwellSensors.begin(), index); 的意图,但这并不能与此错误代码一起编译:

error: 
  no matching function for call to 'advance'
        auto maxIt = std::advance(maxwellSensors.begin(), index);
                     ^~~~~~~~~~~~
/c++/4.6/bits/stl_iterator_base_funcs.h:171:5: note: 
  candidate function [with _InputIterator = std::_Rb_tree_iterator<std::pair<const
  unsigned int, Reader<double, unsigned int>::MaxwellSensor> >,
  _Distance = unsigned int] not viable: expects an l-value for 1st argument
advance(_InputIterator& __i, _Distance __n)

那么如何推进标准地图的迭代器呢?

我也试过auto maxIt = maxwellSensors.begin() + index;,但没有运气。

并且:我想避免这样的 for 循环:

auto maxIt = maxwellSensors.begin();
for(uint i = 0; i < index; ++i){
    ++maxIt;
}

还有其他可能吗? 非常感谢!

【问题讨论】:

  • 您的问题并不完全有道理。您想通过std::advance() 电话获得什么?最后的迭代器?元素“索引”的迭代器?还有什么?
  • 你真的不应该在地图上使用find_if,而应该使用map::find 成员。否则,您首先会放弃使用 map 的所有好处。
  • 基本上你需要阅读你在尝试使用std::advance时得到的编译器错误信息。
  • 该死!我没有只见树木不见森林。 expects an l-value for 1st argument 应该告诉我一切...

标签: c++ iterator stdmap bidirectional stdadvance


【解决方案1】:

std::mapiterator_category双向迭代器。这意味着没有像 Random Access Iterators 那样的O(1) 多步增量。对于后者,你可以这样写:

auto it = my_vector.begin(); // std::vector has random access iterators
std::advance(it, 4);         // NOT a loop, will call it += 4;
it += 4;                     // shorthand, not recommended in generic code 

对于前者,你有

auto it = my_map.begin();    // std::map has bidirectional iterators
std::advance(it, 4);         // for (auto i = 0; i < 4; ++i) ++it;

注意std::advancevoid 返回类型。如果要返回高级迭代器,可以使用std::next

auto it = my_map.begin();
auto it4 = std::next(it, 4); // copies it, then advances and returns that copy

std::advance 的 step 参数可以为负数,在这种情况下,它将在幕后调用 --it。如果要返回递减的迭代器,可以使用std::prev

【讨论】:

    【解决方案2】:

    Advance的原型是:

    template <class InputIterator, class Distance>
      void advance (InputIterator& it, Distance n);
    

    所以你必须这样做:

    auto maxIt = maxwellSensors.begin();
    std::advance(maxIt, index);
    

    而不是

    auto maxIt = std::advance(maxwellSensors.begin(), index); // Failed
    

    【讨论】:

      【解决方案3】:

      您需要提供一个变量来推进。因此,以下将起作用:

      auto it = maxwellSensors.begin();
      std::advance(it, index);
      

      但是,这在内部只是执行您想要避免的循环。循环是推进地图迭代器的唯一方法。如果你使用vector或deque,那么continer.begin() + index是有效的,因为它们有Random Access iterators,而map没有。

      我认为你真正想要的是这个,它在你的地图中找到 index 并返回一个迭代器:

      auto it = maxwellSensors.find(index);
      

      【讨论】:

        【解决方案4】:

        查看预先签名和文档:http://en.cppreference.com/w/cpp/iterator/advance

        template< class InputIt, class Distance >
        void advance( InputIt& it, Distance n );
        

        表示正确的用法是:

        auto maxIt = maxwellSensors.begin();
        std::advance( maxIt , index);
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-09-20
          • 1970-01-01
          • 2011-11-10
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多