سؤال

أحاول تخزين مؤشرات الوظائف العضوية عن طريق القوالب مثل هذا: (هذه نسخة مبسطة من الرمز الحقيقي)

template<class Arg1>
void connect(void (T::*f)(Arg1)) 
{
    //Do some stuff
}

template<class Arg1>
void connect(void (T::*f)()) 
{
    //Do some stuff
}

class GApp
{
public:
    void foo() {}

    void foo(double d) {}
};

ثم أريد أن أفعل مثل ما يلي لكل طرق مثقلة في GAPP:

connect(&GApp::foo); 

دعوة هذا ل foo() على ما يرام، ولكن كيف يمكنني الاتصال بهذا foo(double d)ب لماذا لا يعمل ما يلي؟

connect((&GApp::foo)(double)); 

سوف تعطيني

خطأ بناء الجملة: يجب أن يسبق "Double" مسبقا ")

لا أفهم بناء الجملة الذي يجب استخدامه هنا. قد يكون هذا هو نوع غبي، ولكن يمكن لأي شخص مساعدتي في هذا؟

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

المحلول

الكود الخاص بك كما هو مكتوب لا يجمع. لقد قمت بإجراء بعض "الافتراضات" حول ما تريد القيام به، وقمت بتغيير التعليمات البرمجية.

لتلخيص، يمكنك استدعاء الدالة الصحيحة من خلال تحديد نوع المعلمة الوظيفة بشكل صريح:

connect<double> (&GApp::foo);

إذا كانت طرق الاتصال هي أعضاء في قالب فئة، فمن الضروري فقط تحديد نوع الفصل مرة واحدة:

template <typename T> class A
{
public:
  template<class Arg1>
  void connect(void (T::*f)(Arg1)) 
  {
    //Do some stuff
  }

  void connect(void (T::*f)()) 
  {
    //Do some stuff
  }
};

class GApp
{
public:
    void foo() {}
    void foo(double d) {}
};


int main ()
{
  A<GApp> a;
  a.connect (&GApp::foo);            // foo ()
  a.connect<double> (&GApp::foo);    // foo (double)
}

تحديث:

استجابة لعينة التعليمات البرمجية الجديدة، يتم تمرير جميع المعلومات. الحالة "النادرة" هي حالة "Signal_Void" لأن هذا هو المكان الذي توجد فيه الإشارة حجة قالب، ولكن وظيفة العضو لا. لذلك نحن علبة خاصة في ذلك المثال، ثم انتهينا. تجميع الآن الآن:

template <class Arg = void>
class signal {};
signal<double> signal_double;
signal<> signal_void;

// Arg1 is deduced from signal<Arg1> and then we use it in the declaration
// of the pointer to member function
template<class T, class Arg1>
void connect ( signal<Arg1>& sig, T& obj, void (T::*f)(Arg1) ) {}

// Add special case for 'void' without any arguments
template<class T>
void connect (signal<> & sig, T& obj, void (T::*f)()) {}


void bar ()
{
  GApp myGApp;

  //Connecting foo()
  connect(signal_void, myGApp, &GApp::foo); // Matches second overload

  //Connecting foo(double)
  connect(signal_double, myGApp, &GApp::foo); // Matches first overload
}

نصائح أخرى

لغة البرمجة C ++، 3E، القسم 7.7، P159:

يمكنك أن تأخذ عنوان وظيفة مثقلة عن طريق تعيين مؤشر أو تهيئة مؤشر. في هذه الحالة، يتم استخدام نوع الهدف لتحديد من مجموعة الوظائف الزائدة. علي سبيل المثال:

void f(int);
int f(char);

void (*pf1)(int) = &f;  // void f(int);
int (*pf2)(char) = &f;  // int f(char);
void (*pf3)(char) = &f; // error: no void f(char)

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

connect((&GApp::foo)(double));

يصبح:

void (GApp::*tmp)(double) = &GApp::foo;
connect(tmp);

أبدا استدعاء المتغيرات tmp ;-)

أعتقد أن إيلاء Newacct آمن أيضا، للسبب بالضبط. صب void (GApp::*)(double) يعرف أن تكون هي نفس تهيئة مؤقت من النوع void (GApp::*)(double). وبعد منذ التعبير المستخدم لتهيئة &GApp::foo, ، أتوقع نفس السحر أن ينطبق على المصفاة كما ينطبق على أي تهيئة أخرى مع وظيفة مثقلة. يقول ستروستروب "تهيئة متغير مؤشر إلى وظيفة"، كما يقول "تهيئة مؤشر إلى وظيفة". لذلك يجب أن تشمل المؤخرين.

لذلك إذا كنت تفضل بطانة واحدة:

connect((void (GApp::*)(double))(&GApp::foo));

ومع ذلك، أفترض أن المعيار له نفس فكرة الاتساق كما أفعل، وأنا لم تحقق.

يمكنك محاولة إلقاء المؤشر صراحة، والسماح لها أن تعرف أي واحد لتحديد، مثل هذا:

connect((void (GApp::*)(double))&GApp::foo);

إخلاء المسئولية: لم يختبرها

هذا يعمل،

    typedef void (GApp::*MemberFunctionType)(double); 
    MemberFunctionType pointer = &GApp::foo;


  connect(MemberFunctionType);

لماذا هذا ؟

تعديل

هم .. نعم. هو نفسه مثل حل Newacct. هل يمكن لأي شخص إعطاء حل الثابتة والمتنقلة؟

استخدام دفعة :: مكتبة وظيفة ...

#include <boost/function.hpp>

template<class Arg1>
void connect(boost::function1<void, Arg1*> fn) 
{
    //Do some stuff
}

template<class Arg1>
void connect(boost::function2<void, Arg1*, double> fn) 
{
    //Do some stuff
}

class GApp
{
public:
    void foo() {}

    void foo(double d) {}
};


int main()
{
    boost::function1<void,GApp*> f1 = (void (GApp::*)(void)) &GApp::foo;
    boost::function2<void,GApp*,double> f2 = (void (GApp::*)(double)) &GApp:foo;
    connect(f1);
    connect(f2);
    return 0;
}

الرمز الأصلي الخاص بي هو مثل هذا،

موصلات ....

template<class T, class Arg1>
void connect(signal<Arg1>& sig,T& obj, void (T::*f)()) 
{
//  sig.insert(new GFunction<T, Arg1>(&obj,f));
}

template<class T, class Arg1
void connect(signal<Arg1>& sig,T& obj, void (T::*f)(Arg1)) 
{
//  sig.insert(new GFunction<T, Arg1>(&obj,f));
}

إشارات ...

signal<double> signal_double;
signal<> signal_void;

تطبيق...

class GApp
{
public:
    void foo() {}

    void foo(double d) {}
};

فينالي، ربط ...

//Connecting foo()
        connect(signal_void, myGApp, &GApp::foo()); //Ok

//Connecting foo(double)
        connect(signal_double, myGApp, &GApp::foo()); // but ERROR!

هناك فئات قالب للإشارات (التي لا ذكر هنا). آمل الآن أن يكون الوضع أكثر وضوحا. (أو هل هو نفسه مثل previouse؟). سيعمل هذا الاتصال الثاني إذا لم يكن هناك FOO () (FOO فقط (مزدوج)). هذا هو الشيء الذي يؤذيني رمزي. :(

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