2014-02-07 7 views
3

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

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

И: Я хочу, чтобы избежать для цикла как:

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

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

+0

Ваш вопрос не имеет никакого смысла. Что вы пытаетесь получить со своим вызовом 'std :: advance()'? Итератор для конца? Итератор для элемента «index»? Что-то другое? – SoapBox

+2

Вы действительно не должны использовать 'find_if' на карте, но член' map :: find'. В противном случае вы выбрасываете все преимущества использования «карты» в первую очередь. – pmr

+0

В основном вам нужно прочитать сообщение об ошибке компилятора, которое вы получили, когда пытались использовать 'std :: advance'. –

ответ

7

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.

1

См авансовой подписи и документации: 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); 
2

Вам нужно поставить переменную вперед. Таким образом, будут работать следующие:

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

Однако это внутренне только делает петлю, как вы этого хотели избежать. Петля - единственный способ продвинуть итератор карты. Если вы используете вектор или deque, тогда continer.begin() + index действителен, потому что у них есть Random Access iterators ,, а карта нет.

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

auto it = maxwellSensors.find(index); 
3

Прототип заранее:

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