Вопрос

Прошло много времени с тех пор, как Visual Studio добавила поддержку расширения foreach, которое работает как

vector<int> v(3)
for each (int i in v) {
  printf("%d\n",i);
}

Я хочу знать, как сделать любой класс способным использовать foreach. Нужно ли реализовывать какой-то интерфейс?

Это было полезно?

Решение

для каждого оператора в VC ++, когда используется в неуправляемом классе:

for each (T x in xs)
{
    ...
}

это просто синтаксический сахар для этого:

for (auto iter = xs.begin(), end = xs.end(); iter != end; ++iter)
{
     T x = *iter;
}

Где auto означает, что тип переменной определяется автоматически из типа инициализатора.

Другими словами, вам нужно предоставить методы begin () и end () в вашем классе, которые возвращали бы для него начало и конец входных итераторов.

Вот пример класса, который переносит istream и позволяет перебирать все строки в нем:

#include <istream>
#include <iostream>
#include <fstream>
#include <string>


class lines
{
public:

    class line_iterator
    {
    public:

        line_iterator() : in(0)
        {
        }

        line_iterator(std::istream& in) : in(&in)
        {
            ++*this;
        }

        line_iterator& operator++ ()
        {
            getline(*in, line);
            return *this;
        }

        line_iterator operator++ (int)
        {
            line_iterator result = *this;
            ++*this;
            return result;
        }

        const std::string& operator* () const
        {
            return line;
        }

        const std::string& operator-> () const
        {
            return line;
        }

        friend bool operator== (const line_iterator& lhs, const line_iterator& rhs)
        {
            return (lhs.in == rhs.in) ||
                   (lhs.in == 0 && rhs.in->eof()) ||
                   (rhs.in == 0 && lhs.in->eof());
        }

        friend bool operator!= (const line_iterator& lhs, const line_iterator& rhs)
        {
            return !(lhs == rhs);
        }

    private:

        std::istream* const in;
        std::string line;
    };


    lines(std::istream& in) : in(in)
    {
    }

    line_iterator begin() const
    {
        return line_iterator(in);
    }

    line_iterator end() const
    {
        return line_iterator();
    }

private:

    std::istream& in;
};


int main()
{
    std::ifstream f(__FILE__);
    for each (std::string line in lines(f))
    {
        std::cout << line << std::endl;
    }
}

Обратите внимание, что реализация line_iterator на самом деле несколько больше, чем минимум, необходимый для для каждого ; однако, это минимальная реализация, которая соответствует требованиям входных итераторов, и, таким образом, этот класс также может использоваться со всеми алгоритмами STL, которые работают с входными итераторами, такими как std :: for_each , std: : найти и т. д.

Другие советы

Вы можете использовать это

<код> станд :: for_each

foreach, насколько я знаю, не является частью языка C ++. Это в C #, хотя. Кроме того, я думаю, что у STL и / или Boost есть метод foreach. Возможно, вы думаете об этом?

Ваш класс должен наследовать IEnumerable для использования foreach

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top