Пользовательский итератор в C++

Вы можете использовать запрос для оценки функции , чтобы повысить результат на основе соответствия для фильтра (в данном случае это ram по имени).

Следующий запрос должен работать для вас

POST sort_index/_search
{
    "query": {
        "function_score": {
            "query": {
                "match_all": {}
            },
            "boost": "5",
            "functions": [{
                "filter": {
                    "match": {
                        "name": "ram"
                    }
                },
                "random_score": {},
                "weight": 1000
            }],
            "score_mode": "max"
        }
    },
    "sort": [{
        "activity.keyword": {
            "order": "desc"
        }
    }]
}

29
задан svick 7 July 2013 в 15:29
поделиться

5 ответов

Когда я создал свой собственный итератор (некоторое время назад), я унаследовал от std :: iterator и указал тип в качестве первого параметра шаблона. Надеюсь, это поможет.

Для прямых итераторов используйте в следующем коде имя forward_iterator_tag, а не input_iterator_tag.

Этот класс был изначально взят из класса istream_iterator (и изменен для моего собственного использования, поэтому он может больше не напоминать istram_iterator).

template<typename T>
class <PLOP>_iterator
         :public std::iterator<std::input_iterator_tag,       // type of iterator
                               T,ptrdiff_t,const T*,const T&> // Info about iterator
{
    public:
        const T& operator*() const;
        const T* operator->() const;
        <PLOP>__iterator& operator++();
        <PLOP>__iterator operator++(int);
        bool equal(<PLOP>__iterator const& rhs) const;
};

template<typename T>
inline bool operator==(<PLOP>__iterator<T> const& lhs,<PLOP>__iterator<T> const& rhs)
{
    return lhs.equal(rhs);
}

Просмотрите эту документацию по тегам итератора:
http://www.sgi.com/tech/stl/iterator_tags.html

Просто перечитав информацию об итераторах:
http: // www .sgi.com / tech / stl / iterator_traits.html

Это старый способ работы (iterator_tags), более современный подход - настроить iterator_traits <> для вашего итератора, чтобы он был полностью совместим с STL.

31
ответ дан 28 November 2019 в 00:57
поделиться

Итератор - это просто класс, который поддерживает определенный интерфейс. Как минимум, вы захотите иметь возможность:

  • увеличивать и / или уменьшать его
  • разыменовывать его, чтобы получить объект, на который он «указывает»,
  • проверять его на равенство и неравенство
  • копировать и назначать его

Как только у вас появится класс, который может сделать это разумно для вашей коллекции, вам нужно будет изменить коллекцию, чтобы иметь функции, возвращающие итераторы. Как минимум, вам понадобится

  • функция begin (), которая возвращает экземпляр вашего нового типа итератора, расположенный на первом элементе.
  • функция end (), которая возвращает итератор, который (возможно, условно) расположен на одном конце конец предметов в вашем контейнере
7
ответ дан 28 November 2019 в 00:57
поделиться

Если у вас есть доступ к Boost, использование iterator_facade является наиболее надежным решением и довольно простым в использовании.

22
ответ дан 28 November 2019 в 00:57
поделиться

Проверьте Библиотеку шаблонов представлений .

Особенно проверьте

  1. Union View , представляющий два объединенных контейнера.
  2. Представление конкатенации , представляющее коллекция объединенных контейнеров.
1
ответ дан 28 November 2019 в 00:57
поделиться

Сначала немного обобщим:

typedef int value_type;
typedef std::vector<value_type*> inner_range;
typedef std::vector<inner_range*> outer_range;

Теперь итератор:

struct my_iterator : std::iterator_traits<inner_range::iterator> 
{
    typedef std::forward_iterator_tag iterator_category;

    my_iterator(outer_range::iterator const & outer_iterator, 
                outer_range::iterator const & outer_end)
    : outer_iterator(outer_iterator), outer_end(outer_end)
    { 
        update();
    }

    my_iterator & operator++()
    {
        ++inner_iterator;
        if(inner_iterator == inner_end)
        {
            ++outer_iterator;
            update();
        }
        return *this;
    }

    reference operator*() const
    {   
        return *inner_iterator;
    }

    bool operator==(my_iterator const & rhs) const
    {   
        bool lhs_end = outer_iterator == outer_end;
        bool rhs_end = rhs.outer_iterator == rhs.outer_end;
        if(lhs_end && rhs_end)
            return true;
        if(lhs_end != rhs_end)
            return false;
        return outer_iterator == rhs.outer_iterator 
            && inner_iterator == rhs.inner_iterator;
    }

private:

    outer_range::iterator outer_iterator, outer_end;
    inner_range::iterator inner_iterator, inner_end;

    void update()
    {
        while(outer_iterator != outer_end)
        {
            inner_iterator = (*outer_iterator)->begin();
            inner_end = (*outer_iterator)->end();
            if(inner_iterator == inner_end)
                ++outer_iterator;
            else
                break;
        }
    }    
};

Этот класс предполагает, что внешние итераторы содержат указатели на внутренние диапазоны, что было требованием в вашем вопросе. Это отражено в члене update, в стрелках перед begin() и end(). Вы можете заменить эти стрелки точками, если хотите использовать этот класс в более распространенной ситуации, когда внешний итератор содержит внутренние диапазоны по значению. Обратите внимание, что этот класс не зависит от того, что внутренний диапазон содержит указатели, это нужно знать только клиентам класса.

Код мог бы быть короче, если бы мы использовали boost::iterator_facade, но нет необходимости добавлять зависимость от boost для чего-то настолько простого. Кроме того, единственными сложными частями являются операции равенства и инкремента, а их нам все равно придется написать.

Я оставил следующие члены в качестве "упражнений для читателя":

  • postfix increment iterator
  • operator!=
  • default constructor
  • operator->

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

Пример использования:

int main()
{
    outer_type outer;
    int a = 0, b = 1, c = 2;
    inner_type inner1, inner2;
    inner1.push_back(&a);
    inner1.push_back(&b);
    inner2.push_back(&c);
    outer.push_back(&inner1);
    outer.push_back(&inner2);

    my_iterator it(outer.begin(), outer.end());
                e(outer.end(), outer.end());
    for(; it != e; ++it)
        std::cout << **it << "\n";
}

Что печатает:

0 1 2

18
ответ дан 28 November 2019 в 00:57
поделиться
Другие вопросы по тегам:

Похожие вопросы: