@ IllidanS4 এর উত্তরে বিল্ডিং, আমি একটি টেম্পলেট শ্রেণি তৈরি করেছি যা কার্যত কোনও সদস্য ফাংশনটিকে পূর্বনির্ধারিত যুক্তি এবং শ্রেণীর উদাহরণ সহ পরবর্তী কলিংয়ের জন্য রেফারেন্স দিয়ে পাস করার অনুমতি দেয়।
template<class RET, class... RArgs> class Callback_t {
public:
virtual RET call(RArgs&&... rargs) = 0;
};
template<class T, class RET, class... RArgs> class CallbackCalltimeArgs : public Callback_t<RET, RArgs...> {
public:
T * owner;
RET(T::*x)(RArgs...);
RET call(RArgs&&... rargs) {
return (*owner.*(x))(std::forward<RArgs>(rargs)...);
};
CallbackCalltimeArgs(T* t, RET(T::*x)(RArgs...)) : owner(t), x(x) {}
};
template<class T, class RET, class... Args> class CallbackCreattimeArgs : public Callback_t<RET> {
public:
T* owner;
RET(T::*x)(Args...);
RET call() {
return (*owner.*(x))(std::get<Args&&>(args)...);
};
std::tuple<Args&&...> args;
CallbackCreattimeArgs(T* t, RET(T::*x)(Args...), Args&&... args) : owner(t), x(x),
args(std::tuple<Args&&...>(std::forward<Args>(args)...)) {}
};
পরীক্ষা / উদাহরণ:
class container {
public:
static void printFrom(container* c) { c->print(); };
container(int data) : data(data) {};
~container() {};
void print() { printf("%d\n", data); };
void printTo(FILE* f) { fprintf(f, "%d\n", data); };
void printWith(int arg) { printf("%d:%d\n", data, arg); };
private:
int data;
};
int main() {
container c1(1), c2(20);
CallbackCreattimeArgs<container, void> f1(&c1, &container::print);
Callback_t<void>* fp1 = &f1;
fp1->call();
CallbackCreattimeArgs<container, void, FILE*> f2(&c2, &container::printTo, stdout);
Callback_t<void>* fp2 = &f2;
fp2->call();
CallbackCalltimeArgs<container, void, int> f3(&c2, &container::printWith);
Callback_t<void, int>* fp3 = &f3;
fp3->call(15);
}
স্পষ্টতই, যদি কেবলমাত্র প্রদত্ত যুক্তি এবং মালিক শ্রেণি বৈধ থাকে তবে এটি কাজ করবে। যতদূর পঠনযোগ্যতা ... দয়া করে আমাকে ক্ষমা করুন।
সম্পাদনা: টিপলটিকে সাধারণ স্টোরেজ করে অপ্রয়োজনীয় ম্যালোক সরানো হয়েছে। রেফারেন্সের জন্য উত্তরাধিকারসূত্রে প্রাপ্ত টাইপ। পরিবর্তে কলটাইমে সমস্ত যুক্তি সরবরাহ করার জন্য বিকল্প যুক্ত করা হয়েছে। এখন উভয় থাকার উপর কাজ ....
সম্পাদনা 2: প্রতিশ্রুতি হিসাবে, উভয়। কেবলমাত্র সীমাবদ্ধতা (যা আমি দেখছি) হ'ল কলব্যাক ফাংশনে রানটাইম সরবরাহ করা যুক্তিগুলির আগে পূর্বনির্ধারিত আর্গুমেন্টগুলি অবশ্যই আসতে হবে। জিসিসি সম্মতিতে কিছু সহায়তার জন্য @ শিপস্টারকে ধন্যবাদ। এটি উইন্ডোতে উবুন্টুতে জিসিসি এবং ভিজ্যুয়াল স্টুডিওতে কাজ করে।
#ifdef _WIN32
#define wintypename typename
#else
#define wintypename
#endif
template<class RET, class... RArgs> class Callback_t {
public:
virtual RET call(RArgs... rargs) = 0;
virtual ~Callback_t() = default;
};
template<class RET, class... RArgs> class CallbackFactory {
private:
template<class T, class... CArgs> class Callback : public Callback_t<RET, RArgs...> {
private:
T * owner;
RET(T::*x)(CArgs..., RArgs...);
std::tuple<CArgs...> cargs;
RET call(RArgs... rargs) {
return (*owner.*(x))(std::get<CArgs>(cargs)..., rargs...);
};
public:
Callback(T* t, RET(T::*x)(CArgs..., RArgs...), CArgs... pda);
~Callback() {};
};
public:
template<class U, class... CArgs> static Callback_t<RET, RArgs...>* make(U* owner, CArgs... cargs, RET(U::*func)(CArgs..., RArgs...));
};
template<class RET2, class... RArgs2> template<class T2, class... CArgs2> CallbackFactory<RET2, RArgs2...>::Callback<T2, CArgs2...>::Callback(T2* t, RET2(T2::*x)(CArgs2..., RArgs2...), CArgs2... pda) : x(x), owner(t), cargs(std::forward<CArgs2>(pda)...) {}
template<class RET, class... RArgs> template<class U, class... CArgs> Callback_t<RET, RArgs...>* CallbackFactory<RET, RArgs...>::make(U* owner, CArgs... cargs, RET(U::*func)(CArgs..., RArgs...)) {
return new wintypename CallbackFactory<RET, RArgs...>::Callback<U, CArgs...>(owner, func, std::forward<CArgs>(cargs)...);
}