2008-11-23 4 views
9

У меня есть контейнер, заполненный парами. Я хочу итерации в ней с использованием общих алгоритмов STL (в моем случае это будет inner_product, но рассмотрим его как общую проблему). Алгоритм, который я использую, ожидает итераторов первого и последнего. Могу ли я предоставить специальные итераторы первым и последним, которые будут выполнять итерацию не по парам, а по первому элементу каждой пары?Предоставление итератора для первого элемента контейнера пар

Я знаю, что могу сделать это вручную, предоставляя объект функций ручной работы, который будет обертки вокруг стандартного итератора контейнера, отсрочив его до первого члена пары, предназначенного для самой пары, но я думаю, что есть также умный однострочный, чтобы сделать это для меня. Что бы это могло быть?

+0

Вы имеете в виду, например, у вас есть map.begin(), и вы хотите перебирать его значения (.second)? – 2008-11-23 17:38:08

+0

Да, это еще один пример той же основной проблемы. – 2008-11-23 17:39:04

+0

разрешено увеличение? :) – 2008-11-23 17:49:37

ответ

11

Я огляделся и нашел boost::transform_iterator. Я придумал этот код. Удивительно, насколько хорошо она работает:

#include <map> 
#include <algorithm> 
#include <iostream> 
#include <string> 
#include <iterator> 
#include <boost/iterator/transform_iterator.hpp> 
#include <boost/bind.hpp> 
#include <boost/function.hpp> 

int main() { 
    typedef std::map<std::string, int>::value_type value_type; 
    std::map<std::string, int> a; 
    a["one"] = 1; 
    a["two"] = 2; 

    // returns the second element 
    boost::function<int(value_type&)> f = boost::bind(&value_type::second, _1); 
    std::copy(boost::make_transform_iterator(a.begin(), f), 
       boost::make_transform_iterator(a.end(), f), 
       std::ostream_iterator<int>(std::cout, " ")); 

} 

Это печать "1 2 " на стандартный вывод.

1

Вы можете подкласс, например. std :: vector :: const_iterator самостоятельно, переопределяя оператор * и operator->, чтобы вернуть первую из пары. Вам также необходимо создать свои собственные функции begin() и end(), чтобы вернуть свой пользовательский итератор.

Вы также можете создавать классы двоичных функций и передавать их в inner_product.

1

Нет разумного однострочного решения. Ваша лучшая надежда - написать итератор обертки. На самом деле это довольно каноническое решение. Вы можете проверить, есть ли у Boost уже то, что вам нужно. Если нет, попробуйте написать общую оболочку, которая может быть использована повторно для других проблем.

STL содержит такую ​​итераторную упаковку, которая называется reverse_iterator. Название подразумевает его использование.

1

В конечном счете, я думаю, что ваша идея - путь. Вы можете использовать Boost, чтобы помочь вам это сделать. Для начала вам понадобится функция, которая берет вашу пару и возвращает первый элемент. Я думаю, вы могли бы написать такую ​​функцию в строке, используя Lambda library, но для удобства читаемости я бы просто написал простую функцию, которая делает это вместо этого. Затем передайте эту функцию с вашими оригинальными итераторами для создания transform_iterator для начала и конца вашей последовательности.

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