2013-11-17 6 views
0

Я работаю в среде C++ 03, и применяя функцию к каждому ключу карты много кода:Почему std :: map не предоставляет key_iterator и value_iterator?

const std::map<X,Y>::const_iterator end = m_map.end(); 
for (std::map<X,Y>::const_iterator element = m_map.begin(); element != end; ++element) 
{ 
    func(element->first); 
} 

Если key_iterator существовал тот же код может воспользоваться std::for_each:

std::for_each(m_map.key_begin(), m_map.key_end(), &func); 

Так почему же это не предусмотрено? И есть ли способ адаптировать первый шаблон ко второму?

+0

Y ou может инициализировать как 'it', так и' end' внутри заголовка цикла, например 'for (iterator it = c.begin(), end = c.end(); ...) ', чтобы немного уменьшить количество« кодов ». Тем не менее, предлагая итераторы, которые вы предлагаете, также заставили бы меня задаться вопросом, предоставляют ли они другой порядок или количество элементов, чем простые итераторы, что, в свою очередь, может сделать код менее ясным. –

+1

Ответ на вопрос «Почему стандартная библиотека C++ не имеет X» почти всегда «они не смогли ее добавить». Чтобы что-то было добавлено в библиотеку, кто-то должен написать для нее предложение, комитет должен обсудить это и одобрить, и этого просто не произошло. Этого не существует, потому что никто не положил его туда. – jalf

+0

Случайные ссылки после быстрого поиска: http://stackoverflow.com/questions/1443793/iterate-keys-in-ac-map, http://stackoverflow.com/questions/7667343/creating-a-stl-map- key-iterator, http://stackoverflow.com/questions/110157/how-to-retrieve-all-keys-or-values-from-a-stdmap, http://stackoverflow.com/questions/259240/iterator- адаптер-to-iterate-just-the-values-in-a-map –

ответ

5

Да, это глупый недостаток. Но он легко исправляется: вы можете написать свой собственный общий класс key_iterator, который может быть построен из итератора карты (пары). Я сделал это, это всего лишь несколько строк кода, и тогда тривиально сделать value_iterator.

-1

Там нет необходимости для key_iterator или value_iterator как value_type в виде std::map является std::pair<const X, Y>, и это то, что функция (или функтор) вызывается for_each() будет работать дальше. У отдельных итераторов нет производительности, поскольку pair агрегируется в базовом узле в двоичном дереве, используемом картой.

Доступ к ключу и стоимость через std::pair вряд ли напряжен.

#include <iostream> 
#include <map> 

typedef std::map<unsigned, unsigned> Map; 

void F(const Map::value_type &v) 
{ 
    std::cout << "Key: " << v.first << " Value: " << v.second << std::endl; 
} 

int main(int argc, const char * argv[]) 
{ 
    Map map; 

    map.insert(std::make_pair(10, 20)); 
    map.insert(std::make_pair(43, 10)); 
    map.insert(std::make_pair(5, 55)); 

    std::for_each(map.begin(), map.end(), F); 

    return 0; 
} 

Что дает выход:

Key: 5 Value: 55 
Key: 10 Value: 20 
Key: 43 Value: 10 
Program ended with exit code: 0 
0

Там нет необходимости для std::map<K, V>, чтобы обеспечить итераторы для ключей и/или значений: например итератор может быть легко построен на основе существующего итератора (с). Ну, это не так просто, как нужно/может быть, но это, безусловно, выполнимо. Я знаю, что у Boost есть библиотека итераторных адаптеров.

Реальный вопрос: почему стандартная библиотека C++ не предоставляет итератор-адаптеры для проектных итераторов? Короткий ответ, на мой взгляд, потому что, в общем, вы не хотите изменять итератор, чтобы выбрать доступ к свойствам! Вы скорее хотите проецировать или, что более общее, преобразовать доступное значение, но по-прежнему придерживаться того же понятия позиции. Сформулированные разные, я думаю, что необходимо отделить понятие позиционирования (то есть продвигать итератор и проверять, действительно ли их позиция) от доступа к свойствам в данной позиции. Подход, который я себе это будет выглядеть следующим образом:

std::for_each(m_map.key_pm(), m_map.begin(), m_map.end(), &func); 

или, если вы знаете, что основная структура, полученная из итератора карты содержат является std::pair<K const, V> (как это имеет место для std::map<K, V>, но не обязательно для других контейнеров, аналогичных ассоциативных контейнеров , например, ассоциативный контейнер на основе B-дерева выиграют от разделения ключа и значения в отдельные юридические лица):

std::for_each(_1st, m_map.begin(), m_map.end(), &func); 

Мой STL 2.0 page является для параметра [незавершенные] рецензия с немного более подробно о том, как Я думаю, что стандартные алгоритмы библиотеки C++ должны быть улучшены, в том числе разделение итераторов на позиционирование (курсоры) и доступ к свойствам (карты свойств).

0

Так почему же это не предусмотрено?

Я не знаю.

И есть ли способ адаптировать первый шаблон ко второму?

В качестве альтернативы, чтобы сделать «ключ итератора» (см мой комментарий и другие ответы), вы можете написать небольшую обертку вокруг func, например:

class FuncOnFirst { // (maybe find a better name) 
public: 
    void operator()(std::map<X,Y>::value_type const& e) const { func(e.first); } 
}; 

затем использовать:

std::for_each(m_map.begin(), m_map.end(), FuncOnFirst()); 

Чуть более общая обертка:

class FuncOnFirst { // (maybe find a better name) 
public: 
    template<typename T, typename U> 
    void operator()(std::pair<T, U> const& p) const { func(p.first); } 
}; 

 Смежные вопросы

  • Нет связанных вопросов^_^