2009-10-26 7 views
5

Ha sido un tiempo desde Visual Studio ha añadido soporte para una extensión foreach que funciona comoCómo escribir una clase capaz de foreach

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

Quiero saber cómo hacer cualquier clase capaz de utilizar foreach. ¿Debo implementar alguna interfaz?

+0

anyting MS compilador nunca apoyó al igual que para el código C++. Supongo que estás hablando de otro idioma. DO#? Si es así, debes repetir tu pregunta. – AnT

+3

http://msdn.microsoft.com/en-us/library/ms177202%28VS.80%29.aspx – stelonix

+2

Quizás la etiqueta C++ deba ser una etiqueta vC++. Esto ciertamente no es una pregunta estándar de C++. – MAK

Respuesta

10

for each comunicado en VC++, cuando se utiliza en una clase no administrada:

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

es sólo azúcar sintáctico para esto:

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

Dónde auto significa que tipo de variable se deduce automáticamente de tipo de inicializador

En otras palabras, debe proporcionar los métodos begin() y end() en su clase que devolverían iteradores de entrada y fin de entrada para él.

Aquí es un ejemplo de la clase que envuelve un istream y le permite iterar sobre todas las líneas en él:

#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; 
    } 
} 

Nota que la aplicación de line_iterator es en realidad un poco más grande que el mínimo necesario por for each; sin embargo, es la puesta en práctica mínima que se ajusta a los requisitos de iterador de entrada, y por lo tanto esta clase también se puede utilizar con todos los algoritmos de STL que trabajan en los iteradores de entrada, tales como std::for_each, etc. std::find

+0

¿Puedes dar el ejemplo más simple de una clase implementando aquellos que se compilarán? Solo necesito saber los tipos de retorno de los métodos y cualquier otra cosa que me falte, porque no puedo compilar con una clase simple – stelonix

+0

. Necesita proporcionar iteradores de inicio y final. – GManNickG

+0

Respuesta actualizada para incluir un ejemplo. Los tipos de retorno reales no importan, siempre y cuando admitan todas las operaciones implícitas en la expansión descrita de 'para cada uno'. –

0

foreach no es parte del lenguaje C++ hasta donde yo sé. Sin embargo, está en C#. Además, creo que STL y/o Boost tienen un método foreach. Quizás estás pensando en eso?

+1

Soy consciente de que no es parte del lenguaje y también soy consciente de que hay un foreach en el STL y en Boost. Sin embargo, el compilador de Visual Studio es compatible con foreach en la forma en que lo mostré como una extensión de compilación, y me gustaría saber cómo crear clases que funcionen con él. – stelonix

+0

Ah bien, lo siento por malentendido. –

+0

Downvoted por malentendido, luego disculparse por ello? Resulta que alguien fue a una juerga downvoting. –

1

Puede utilizar esta

std::for_each

+0

+1 Prefiera los estándares a las extensiones no estándar siempre que sea posible. –

+3

'std :: for_each' no es realmente un reemplazo porque no le permite especificar el bloque de código para ejecutar para cada iteración en línea. En la práctica, casi nunca veo 'std :: for_each' usado precisamente por esta razón; es más fácil escribir un viejo bucle' for' con iteradores. En cuanto a "para cada uno", definitivamente no tiene ningún lugar en el código portátil, pero no todos los códigos son significativamente portátiles de todos modos. Si su aplicación ya está escrita usando MFC o ATL, entonces está atrapado con VC++ de todos modos, y tampoco hay nada de malo en utilizar sus extensiones de idioma. –

+0

Bueno, si la portabilidad no es un requisito, me gustaría ejecutar funciones lambda en el grupo y votar esta respuesta. Es probable que algunos compiladores los implementen ahora o muy pronto, y de hecho harán de 'std :: for_each' la mejor solución, ya que se convertirán en el estándar que (con suerte) todos los compiladores admitirán. – sbi

-2

Su clase debe heredar IEnumerable usar foreach

Cuestiones relacionadas