تعزيز templating :: اربط بالتعامل تلقائيًا مع وسيطات متعددة لوظيفة الأعضاء

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

سؤال

لدي فئة مع وظيفة "إرفاق" تقبل كائن وظيفة وتخزينها في مجموعة. الفئة نفسها تمثل على توقيع الوظيفة. شيء من هذا القبيل:

template<class Signature>
class Event
{
public:

 void Attach(boost::function<Signature> signature)
 {
  MySignatures.push_back(signature);
 }

private:

 std::list<boost::function<Signature>> MySignatures;
};

لإظهار الاستخدام ، فكر في الفصل التالي:


class Listening
{
public:

 int SomeFunction(int x, int y, int z); 
};

لتمرير الوظيفة على Listening داخل Event, ، سأحتاج إلى الكتابة:


 Event<int(int, int, int)> myEvent;
 Listening myListening;

 myEvent.Attach(boost::bind(boost::mem_fn(&Listening::SomeFunction), &myListening, _1, _2, _3));

لذا بدلاً من القيام بذلك لكل حالة قد تكون عرضة للخطأ ، أكتب مجموعة من وحدات الماكرو ، على النحو التالي:


 #define EventArgument0(x, y)  boost::bind(boost::mem_fn(x), y)
 #define EventArgument1(x, y)  boost::bind(boost::mem_fn(x), y, _1)
 #define EventArgument2(x, y)  boost::bind(boost::mem_fn(x), y, _1, _2)
 #define EventArgument3(x, y)  boost::bind(boost::mem_fn(x), y, _1, _2, _3)
 #define EventArgument4(x, y)  boost::bind(boost::mem_fn(x), y, _1, _2, _3, _4)

 etc.

ثم يمكنني الكتابة:


 myEvent.Attach(EventArgument3(&Listening::SomeFunction, &myListening));

وهو أسهل بكثير للقراءة (على ما أظن). الآن على سؤالي: كيف يمكنني الكتابة بدلاً من ذلك:


 myEvent.Attach(EventArgument(&Listening::SomeFunction, &MyListening));

أو حتى أفضل:


 myEvent.Attach(&Listening::SomeFunction, &myListening);

, ، بحيث يرتبط إرفاق الحدث بطريقة سحرية مع العدد المناسب من الوسائط كما هو موجود فيu003CSignature> (في هذا المثال، int(int, int, int)))؟ أنا منفتح على أي قالب سحر برمجة الفوقية التي تفكر فيها هنا.

شكرًا.

تحرير: اتضح أنني لست بحاجة boost::mem_fn هنا ، لأن boost::bind هو مكافئ ، لذلك في بلدي الكلي يمكنني استخدام:

bind(&MyClass::Hello, myClass, _1, _2, _3);

،بدلاً من:

bind(mem_fn(&MyClass::Hello), myClass, _1, _2, _3);

ومع ذلك ، يبقى السؤال: كيف تمر &MyClass::Hello إلى فئة الحدث واستخدم القالب الزائد للتعامل مع _1, _2, _3, ، إلخ Event صف دراسي؟

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

المحلول

الحمل الزائد Attach لأرقام مختلفة من المعلمات في وظيفة العضو:

template<typename R,typename T,typename U>
void Attach(R (T::*pmf)(),U* p))
{
    Attach(boost::bind(pmf,p));
}

template<typename R,typename T,typename U,typename A1>
void Attach(R (T::*pmf)(A1),U* p))
{
    Attach(boost::bind(pmf,p,_1));
}

template<typename R,typename T,typename U,typename A1,typename A2>
void Attach(R (T::*pmf)(A1,A2),U* p))
{
    Attach(boost::bind(pmf,p,_1,_2));
}

إذا كنت بحاجة إلى التعامل معها const وظائف الأعضاء أيضًا ، ستحتاج إلى مجموعة ثانية من الأحمال الزائدة.

نصائح أخرى

تحضير Attach() سيسمح لك النموذج بالقيام بما تهدف إليه. يصبح الرمز فوضويًا ولكنه يتيح لك أن نسميه بالطريقة التي تريدها.

template<typename A1>
void Attach(A1 a1);

template<typename A1, typename A2>
void Attach(A1 a1, A2 a2);

template<typename A1, typename A2, typename A3>
void Attach(A1 a1, A2 a2, A3 a3);

template<typename A1, typename A3, typename A4>
void Attach(A1 a1, A2 a2, A3 a3, A4 a4);
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top