He encontrado a mí mismo escribiendo

for(int i=0;i<myvec.size();i++)
   myvec[i]->DoWhatever(param);

mucho, y me gustaría comprimir en un foreach declaración, pero no estoy seguro de cómo obtener param de allí sin ir super detallado. Yo también tengo cosas como

for(int i=0;i<myvec.size();i++)
   if(myvec[i]->IsOK())
      myvec[i]->DoWhatever(param);

y me gustaría volver a escribir ese tipo también. Los pensamientos?

Oh, también, por diversas razones, no quiero usar el boost.

InformationsquelleAutor Jesse Beder | 2009-01-24

6 Comentarios

  1. 15
    #include <vector>
    #include <algorithm>
    #include <functional>
    
    class X
    {
        public:
            void doWhat(int x) {}
            bool IsOK() const {return true;}
    };
    class CallWhatIfOk
    {
        public:
            CallWhatIfOk(int p): param(p) {}
    
            void operator()(X& x) const
            {   if (x.IsOK())    {x.doWhat(param);}}
        private:
            int param;
    };
    
    int main()
    {
        std::vector<X>      myVec;
    
        std::for_each(  myVec.begin(),
                        myVec.end(),
                        std::bind2nd(std::mem_fun_ref(&X::doWhat),4)
                     );
    
    
        std::for_each(  myVec.begin(),
                        myVec.end(),
                        CallWhatIfOk(4)
                     );
    }
  2. 6

    Oh, también, por diversas razones, no quiero usar el boost.

    Decisión válida, pero lo más probable es el equivocado. Considere la posibilidad de Impulsar como una extensión de la STL. C++ es una biblioteca lenguaje orientado. Si usted no toma esto en cuenta, el código será cualitativamente inferiores.

    Mientras std::for_each puede ser utilizado aquí, la ausencia de expresiones lambda en C++ hasta C++0x hace que este tedioso. Yo defiendo el uso de Boost.ForEach! Se hace de esta mucho más fácil:

    foreach (yourtype x, yourvec)
        if (x.IsOK())
            x.Whatever();
    • Por desgracia, no es mi decisión si se debe usar el boost.
    • Podría querer decir que no usar el boost a continuación. Diciendo que no quiero es simplemente buscar un argumento… 😉
    • ¿Qué acerca de no?
  3. 4

    Mi solución preferida es por lo general para escribir un functor a hacer lo que tengo:

    struct doWhatever {
      doWhatever(const Param& p) p(p) {}
      void operator(MyVec v&, Param p) {
        v.DoWhatever(param);
      }
    
    private:
      Param p;
    };

    Y, a continuación, el bucle:

    std::for_each(myvec.begin(), myvec.end(), doWhatever(param));

    Dependiendo de cómo muchas variaciones de este tiene, este podría ser un poco demasiado detallado.
    Hay un montón de opciones para hacerlo en línea, sin embargo.
    boost::lambda permita construir la función que usted necesita en la llamada-sitio. boost::bind (o el de la biblioteca estándar de enlazar funciones) le permiten enlazar el parámetro parámetro a la función, así que usted no necesita proporcionar un argumento cada vez.

    boost::lambda es probablemente la manera más concisa y flexible. Yo normalmente uso la llanura functor enfoque porque la sintaxis es más fácil de recordar. 😉

    • Esto es lo que tenía, y tenía la esperanza de evitar) 🙂
    • hm, sin impulso (ouch), no creo que usted puede hacer que sea mucho más corto. En algunos de los casos, el std::bind_* cosas podría ayudar, pero no hay ninguna milagrosa balas de plata. (Al menos hasta que c++0x con la adición de expresiones lambda)
  4. 3

    bien cuando tenemos compiladores que el soporte de C++0x lambda expresiones, este se convierte en sencillo y mínimamente invasiva:

    std::for_each(myvec.begin(),myvec.end(),[&](X& item){
         item->DoWhatever(param);
    });

    y el segundo ejemplo puede tener este aspecto:

    std::for_each(myvec.begin(),myvec.end(),[&](X& item){   
       if(item->IsOK())      
          myvec[i]->DoWhatever(param);
    });
    • Que es tan lástima, no funciona en g++ :(. Espero que en algún momento voy a ser capaz de utilizar esas construcciones…
  5. 3
    #include <vector>
    #include <algorithm>
    #include <boost/bind.hpp>
    #include <boost/lambda/if.hpp>
    #include <boost/lambda/bind.hpp>
    struct A
    {
    bool IsOK () { return true; }
    void DoWhatever (int param) {}
    };
    struct B
    {
    bool IsOk (A * a) { return true; }
    void DoWhatever (A * a, int param) {}
    };
    typedef std::vector<A *> Myvec;
    void main()
    {
    Myvec myvec;
    int param = 1;
    B b;
    //first challenge using boost::bind (fnct in the same class)
    std::for_each (myvec.begin(), myvec.end(),
    boost::bind (&A::DoWhatever, _1, param));
    //first challenge using boost::bind (fnct in an external class)
    std::for_each (myvec.begin(), myvec.end(),
    boost::bind (&B::DoWhatever, &b, _1, param));
    //second challange using boost::lambda (fnct in the same class)
    std::for_each (myvec.begin(), myvec.end(),
    boost::lambda::if_then(
    boost::lambda::bind (&A::IsOK, boost::lambda::_1), 
    boost::lambda::bind (&A::DoWhatever, boost::lambda::_1, param)
    )
    );
    //second challange using boost::lambda (fnct in an external class)
    std::for_each (myvec.begin(), myvec.end(),
    boost::lambda::if_then(
    boost::lambda::bind (&B::IsOK, &b, boost::lambda::_1), 
    boost::lambda::bind (&B::DoWhatever, &b, boost::lambda::_1, param)
    )
    );
    }

    Puede simplificar mediante el uso de espacios de nombres…

  6. 0

    Si usted está usando GCC puede definir algo como:

    #define foreach(element, array) \
    for(typeof((array).begin()) element = (array).begin(), __end_##element = (array).end();\
    element != __end_##element;\
    ++element)

    y utilizarla después como este:

    foreach(element, array){
    element->DoSomething(); //or (*element)->DoSomething() if type is already a pointer
    }

    Yo uso este en una matriz personalizada pero funciona bien con std::vector demasiado.

Dejar respuesta

Please enter your comment!
Please enter your name here