Como escrever uma classe capaz de foreach
-
06-07-2019 - |
Pergunta
Tem sido um tempo desde que Visual Studio adicionou suporte para uma extensão foreach que funciona como
vector<int> v(3)
for each (int i in v) {
printf("%d\n",i);
}
Eu quero saber como fazer qualquer classe capaz de usar foreach. Eu preciso implementar algumas interface?
Solução
declaração for each
no VC ++, quando usado em uma classe não de gestão:
for each (T x in xs)
{
...
}
é o açúcar apenas sintática para isso:
for (auto iter = xs.begin(), end = xs.end(); iter != end; ++iter)
{
T x = *iter;
}
Onde meios auto
esse tipo de variável é deduzido automaticamente de tipo de initializer.
Em outras palavras, você precisa fornecer métodos begin()
e end()
em sua classe que voltaria começar e entrada fim iterators para ele.
Aqui está um exemplo de classe que envolve um istream
e permite que você iterar sobre todas as linhas em que:
#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;
}
}
Note que a implementação do line_iterator
é realmente um pouco maior do que o mínimo necessário por for each
; no entanto, é a implementação mínima que está em conformidade com requisitos de entrada iterador, e, assim, esta classe também é utilizável com todos os algoritmos STL que os trabalhos sobre iteradores de entrada, como std::for_each
, std::find
etc.
Outras dicas
Você pode usar este
std::for_each
foreach não é parte da linguagem C ++, tanto quanto eu sei. É em C # embora. Além disso, acho STL e / ou impulso tem um método foreach. Talvez você esteja pensando sobre isso?
Sua classe deve herdar IEnumerable usar foreach