Предоставление итератора для первого элемента контейнера пар - PullRequest
9 голосов
/ 23 ноября 2008

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

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

Ответы [ 4 ]

11 голосов
/ 23 ноября 2008

Я оглянулся и нашел 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 голос
/ 23 ноября 2008

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

1 голос
/ 23 ноября 2008

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

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

1 голос
/ 23 ноября 2008

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...