20

私は自分が書いていることに気づきました

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

たくさんあり、これをステートメントに圧縮したいのですが、超冗長にならずにそこforeachに入る方法がわかりません。param私も

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

あの男も書き直したいです。何かご意見は?

ああ、また、いろいろな理由で、私はブーストを使いたくありません。

4

6 に答える 6

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)
                 );
}
于 2009-01-24T19:05:47.837 に答える
6

あ、あと諸事情によりブーストは使いたくないです。

妥当な決定ですが、おそらく間違った決定です。Boost を STL の拡張と考えてください。C++ はライブラリ駆動型言語です。これを考慮しないと、コードの質が低下します。

whilestd::for_eachはここで使用できますが、C++0x までは C++ にラムダ式がないため、これは面倒です。Boost.ForEachを使用することをお勧めします! これにより、これがはるかに簡単になります。

foreach (yourtype x, yourvec)
    if (x.IsOK())
        x.Whatever();
于 2009-01-24T19:06:27.850 に答える
4

私が好む解決策は、通常、必要なことを行うためのファンクターを作成することです。

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));

これのバリエーションがいくつあるかにもよりますが、これは少し冗長すぎるかもしれません。ただし、インラインで実行するためのオプションはたくさんあります。boost::lambda を使用すると、呼び出しサイトで必要な関数を構築できます。boost::bind (または標準ライブラリ bind 関数) を使用すると、パラメーター param を関数にバインドできるため、毎回引数として指定する必要がありません。

boost::lambda は、おそらく最も簡潔で柔軟なアプローチです。構文が覚えやすいので、通常は単純なファンクター アプローチを使用します。;)

于 2009-01-24T19:14:13.890 に答える
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)
    )
  );

}

名前空間を使用して単純化できます...

于 2010-04-13T22:33:58.467 に答える
0

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 でも正常に動作します。

于 2010-06-01T17:27:06.390 に答える