The main question is already in the title: How do I advance the iterator of a standard map?
But since most people ask why I need this, I'll provide some more information: I have a class which has several maps. I have at least 2 differential equations, at least 2 sensor types (field, or dft) and at least 2 space types (volume, surface). I need to save all these things, and make a correlation between them. So I thought it would be wise, to have maps of these things, and when the things are correlated with each other, they have the same key in their maps.
For simplicity we only consider three maps.
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
}
};
In the course of my programm I need to instantiate several variables of a SensorInterface
.
For that I need to know how many maxwell sensors I have, and then iterate through the maxwell sensors and get the members of the other sensors.
This looks like:
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);
}
}
So the function in the reader should look like:
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;
}
}
So... This is the intention for std::advance(maxwellSensors.begin(), index);
But this doesn't compile with this error code:
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)
So how can I advance the iterator of a standard map?
I also tried auto maxIt = maxwellSensors.begin() + index;
but without luck.
And: I want to avoid a for loop like:
auto maxIt = maxwellSensors.begin();
for(uint i = 0; i < index; ++i){
++maxIt;
}
Is there any other possibility? Many thanks in advance!
The iterator_category
of a std::map
is that of a Bidirectional Iterator. This means that there is no O(1)
multi-step increment such as you have for Random Access Iterators. For the latter, you can write:
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
For the former, you have
auto it = my_map.begin(); // std::map has bidirectional iterators
std::advance(it, 4); // for (auto i = 0; i < 4; ++i) ++it;
Note that std::advance
has void
return type. If you want to return an advanced iterator, you can use std::next
auto it = my_map.begin();
auto it4 = std::next(it, 4); // copies it, then advances and returns that copy
The step parameter for std::advance
can be negative, in which case it will call --it
under the covers. If you want to return a decremented iterator, you can use std::prev
.
The prototype of advance is:
template <class InputIterator, class Distance>
void advance (InputIterator& it, Distance n);
So you have to do:
auto maxIt = maxwellSensors.begin();
std::advance(maxIt, index);
instead of
auto maxIt = std::advance(maxwellSensors.begin(), index); // Failed
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With