كيفية استخدام الأمراض المنقولة جنسيا :: foreach مع المعلمات / تعديل

StackOverflow https://stackoverflow.com/questions/476488

  •  20-08-2019
  •  | 
  •  

سؤال

ولقد وجدت نفسي أكتب

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

ووأود أن كتابة هذا الرجل أيضا. أي أفكار؟

وأوه، أيضا، لأسباب مختلفة، وأنا لا أريد أن استخدام دفعة.

هل كانت مفيدة؟

المحلول

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

نصائح أخرى

<اقتباس فقرة>   

وأوه، أيضا، لأسباب مختلفة، وأنا لا أريد أن استخدام دفعة.

وصالح القرار، ولكن على الأرجح خطأ واحد. النظر في زيادة امتدادا إلى المحكمة الخاصة بلبنان. C ++ هي لغة يحركها المكتبة. إذا كنت لا تأخذ هذا الأمر بعين الاعتبار، سوف شفرة لديك أدنى نوعيا.

وعلى الرغم std::for_each يمكن استخدامها هنا، وغياب تعبيرات لامدا في C ++ حتى C ++ 0X يجعل هذا مملة. وأنا أؤيد استخدام Boost.ForEach ! يجعل هذا <م> كثير أسهل:

foreach (yourtype x, yourvec)
    if (x.IsOK())
        x.Whatever();

وبلدي الحل المفضل هو عادة لكتابة functor أن تفعل ما أحتاج:

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

واعتمادا على عدد من الاختلافات هذا لديك، وهذا قد يكون قليلا مطول جدا. هناك الكثير من الخيارات لفعل ذلك على الرغم من المضمنة. تعزيز :: أن امدا تمكنك من بناء وظيفة تحتاجها من الموقع المكالمة. تعزيز :: ربط (أو وظائف مكتبة ربط القياسية) سوف تمكنك من ربط المعلمة المعلمة إلى الدالة بحيث لا تحتاج إلى تزويدها كحجة في كل مرة.

ودفعة :: امدا وربما كان النهج الأكثر إيجازا ومرونة. وعادة ما تستخدم نهج functor عادي لأن بناء الجملة يسهل تذكرها. ؛)

وكذلك عندما يكون لدينا المجمعين التي تدعم C ++ 0X expresions امدا، وهذا يصبح واضحة والغازية الحد الأدنى:

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

}

ويمكنك تبسيط ذلك باستخدام النطاقات ...

إذا كنت تستخدم دول مجلس التعاون الخليجي يمكنك تحديد شيء من هذا القبيل:

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

وأنا استخدم هذا على مجموعة مخصصة لكنه يعمل بشكل جيد مع الأمراض المنقولة جنسيا :: ناقلات أيضا.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top