تعزيز templating :: اربط بالتعامل تلقائيًا مع وسيطات متعددة لوظيفة الأعضاء
-
29-09-2019 - |
سؤال
لدي فئة مع وظيفة "إرفاق" تقبل كائن وظيفة وتخزينها في مجموعة. الفئة نفسها تمثل على توقيع الوظيفة. شيء من هذا القبيل:
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);