Как использовать станд.:: foreach с параметрами/модификацией

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

20
задан Rex M 28 April 2009 в 23:23
поделиться

6 ответов

#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)
                 );
}
15
ответ дан 30 November 2019 в 00:32
поделиться

, О, также, по различным причинам, я не хочу использовать повышение.

Допустимое решение, но скорее всего неправильное. Рассмотрите Повышение как расширение STL. C++ является управляемым библиотекой языком. Если Вы не примете это во внимание, то Ваш код будет качественно нижним.

, В то время как std::for_each может использоваться здесь, отсутствие лямбда-выражений в C++ до C++, 0x делает это утомительным. Я рекомендую использовать Повышение. ForEach! Это делает это очень легче:

foreach (yourtype x, yourvec)
    if (x.IsOK())
        x.Whatever();
6
ответ дан 30 November 2019 в 00:32
поделиться

Мое предпочтительное решение состоит в том, чтобы обычно писать функтор, чтобы сделать то, в чем я нуждаюсь:

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

private:
  Param p;
};

И затем цикл:

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

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

повышение:: лямбда является, вероятно, самым кратким и гибким подходом. Я обычно использую простой подход функтора, потому что синтаксис легче помнить. ;)

4
ответ дан 30 November 2019 в 00:32
поделиться

хорошо, когда у нас есть компиляторы, которые поддерживают C++ 0x выражения лямбды, это становится простым и минимально агрессивным:

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

и второй пример может быть похожим на это:

std::for_each(myvec.begin(),myvec.end(),[&](X& item){   
   if(item->IsOK())      
      myvec[i]->DoWhatever(param);
});
3
ответ дан 30 November 2019 в 00:32
поделиться
#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)
    )
  );

}

Вы можете упростить это, используя пространства имен ...

3
ответ дан 30 November 2019 в 00:32
поделиться

Если вы используете GCC, вы можете определить что-то вроде:

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

и использовать его после этого:

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

Я использую это на настраиваемый массив, но он отлично работает и с std :: vector.

0
ответ дан 30 November 2019 в 00:32
поделиться
Другие вопросы по тегам:

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