Перегруженный указатель функции-члена на шаблон

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

Вопрос

Я пытаюсь хранить указатели на функции-члены с помощью шаблонов, подобных этому:(Это упрощенная версия моего реального кода)

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

Если методы connect являются членами шаблона класса, то указать тип класса необходимо только один раз:

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, стр. 159:

Вы можете получить адрес перегруженной функции, присвоив ей указатель на функцию или инициализировав его.В этом случае тип целевого объекта используется для выбора из набора перегруженных функций.Например:

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.Кто-нибудь может дать решение, пожалуйста?

Использование boost:: библиотека функций...

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

Существуют шаблонные классы для сигналов (которые здесь не упоминаются).Я надеюсь, что теперь ситуация более прояснилась.(или это то же самое, что и в предыдущем случае?).Это второе соединение будет работать, если нет foo() (только foo(double)).Это то, из-за чего мой код причинил мне боль.:(

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top