продвигать итератор стандартной карты

Главный вопрос уже в заголовке: Как мне продвинуть итератор стандартной карты?

Но так как большинство людей спрашивают, зачем мне это нужно, я предоставлю еще немного информации:
У меня есть класс, который имеет несколько карт. У меня есть как минимум 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;
}

Есть ли другая возможность?
Спасибо заранее!

3

Решение

iterator_category из std::map это из Двунаправленный итератор. Это означает, что нет 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::advance имеет void тип возврата. Если вы хотите вернуть расширенный итератор, вы можете использовать std::next

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

Параметр шага для std::advance может быть отрицательным, в этом случае он будет вызывать --it под одеялом. Если вы хотите вернуть уменьшенный итератор, вы можете использовать std::prev,

8

Другие решения

Прототипом продвижения является:

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);

Тем не менее, это внутренне просто делает цикл, как вы хотели избежать. Цикл — единственный способ продвинуть итератор карты. Если вы используете вектор или deque, то continer.begin() + index действует, потому что у них есть Random Access iterators,, пока карты нет.

Я думаю, что вы действительно хотите это то, что находит index в вашей карте и возвращает к ней итератор:

auto it = maxwellSensors.find(index);
2

Смотрите предварительную подпись и документацию: 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);
1