LINUX.ORG.RU

[C++][boost::signals2] Каковы сигнатуры операторов operator () в плюсах?

 


0

0

Потребовалось прицепить сигналы/слоты из boost-а к классу, у которого перегружен operator (). Пример может выглядеть так:

#include <iostream>
#include <boost/bind.hpp>
#include <boost/signals2.hpp>
//----------------------------------------------------------
typedef boost::signals2::signal<void (void)> VoidSignal;
typedef VoidSignal::slot_type VoidSlot;
struct Listener
{
 void operator () (void)
 { std::cerr<<"operator () (void)"<<std::endl; }
 void operator () (int value)
 { std::cerr<<"operator () (int)"<<std::endl; }
};
//----------------------------------------------------------
int main(int argc,char** argv)
{
 Listener listener;
 VoidSignal sig;
 sig.connect(VoidSlot(&Listener::operator (),&listener));
 /* Если у класса удалить operator () (int), то предыдущая строка компилируется */
 sig();
 sig.disconnect(boost::bind(&Listener::operator (),&listener));
 /* И здесь та же проблема */
 sig();
 return 0;
}

Что нужно подставить в первые параметры ViodSlot и bind при наличии нескольких operator () ?

&Listener::operator () - как бедный компилятор определит, какая из перегрузок тебе нужна.

Тебе надо получить адресс, а потом уже применять static_cast к этому адресу

namezys ★★★★
()
Ответ на: комментарий от namezys

> как бедный компилятор определит, какая из перегрузок тебе нужна

Это-то я понимаю, что он не понимает, какого из операторов ему дёргать. Вопрос в том, как явно указать сигнатуру? Хотя, у VoidSignal-же указано и возвращаемое значение, и параметр (void). Отчего конпелятор не может применить эти знания при разрешении перегрузки?

one_more_hokum ★★★
() автор топика
Ответ на: комментарий от namezys

список конструкторов VoidSlot в студию

Э-э-э... Вот это ты спрашиваешь? Я полагаю, что в моём случае используется третий конструктор, который

template<typename Func, typename Arg1, typename Arg2, ..., typename ArgN>
slot(const Func & f, const Arg1 & a1, const Arg2 & a2, ..., const ArgN & aN);
one_more_hokum ★★★
() автор топика
Ответ на: комментарий от one_more_hokum

Вот и ответ. не удается инстантиировать конструктор, так как Func - неопределенный тип. Сделай его определенным - будет работать

namezys ★★★★
()
Ответ на: комментарий от Begemoth
sig.connect(VoidSlot((void (Listener::*)()&Listener::operator (),&listener));

Ругается... Я через bind сделал:

typedef boost::signals2::signal<void (void)> VoidSignal;
//...
sig.connect(VoidSlot(boost::bind(&Listener::operator (),&listener)));

Вот только, если сказать

typedef boost::signals2::signal<void (int)> VoidSignal;
//...
sig.connect(VoidSlot(boost::bind(&Listener::operator (),&listener)));
sig(100500);

то всё равно будет вызываться operator () (void), а не operator () (int), и никаких подозрений при компиляции. Странно.

one_more_hokum ★★★
() автор топика
Ответ на: комментарий от namezys

> это для функций с одним парамтером

Это я помню. Меня удивляет то, что сигнатура VoidSignal-у передана на функцию с одним параметром, а bind привязку делает к функции без параметров. И почему конпелятор не возмущается?

one_more_hokum ★★★
() автор топика
Ответ на: комментарий от one_more_hokum

так.. а теперь включаем голову xD

sig.connect(VoidSlot(boost::bind(&Listener::operator (),&listener))); sig(100500);

посмотри как ты биндишь и к чему... у компилера кагбы и вариантов-то нед.. ты биндишь к void Listener::operator () (void)

можно сделать например вот так:

#include <boost/lambda/lambda.hpp>

...

sig.connect(VoidSlot(boost::bind(&Listener::operator (),&listener, _1)));

а вообще - посмотри в сторону boost:function

anonymous
()
Ответ на: комментарий от anonymous

лямбду может и необязат подключать - по-скорому накидал

anonymous
()
Ответ на: комментарий от anonymous

> ты биндишь к void Listener::operator () (void)

Или у меня голова не включается, или ещё что... Я не понимаю, отчего конпелятор не вызверился на переданную signal-у сигнатуру, там же в параметрах не void, а вовсе даже int.

one_more_hokum ★★★
() автор топика
Ответ на: комментарий от one_more_hokum

ок. понял.

смотри на строчку, где биндишь, забудь про определение VoidSginal

sig.connect(VoidSlot(boost::bind(&Listener::operator (),&listener)));

т.е.: boost::bind(&Listener::operator (),&listener)

какую функцию ты тут биндишь?

anonymous
()

У меня как у новичка вопрос. Почему вы пишите std:: вместо того чтобы написать using namespace std; ?

Andaril
()
Ответ на: комментарий от Andaril

Зачем засирать текущее пространство имен, если ты редко обращаешься к std

std:: - это 5 символов. Но в результате ты работаешь в «чистом» пространстве

namezys ★★★★
()
Ответ на: комментарий от Andaril

нет, я конкретизирую что использую..

т.е. например:

using boost::bind;
dpt-ru
()
Ответ на: комментарий от one_more_hokum

тот аноним - это я (я теперь зарегилсо xD)

вот тебе рабочий пример. кста читай документацию (у тебя же объект-функция, нафига тогда биндить как ты?) - http://www.boost.org/doc/libs/1_44_0/libs/bind/bind.html , секция «Using bind with function objects»

#include <iostream>
#include <boost/bind.hpp>
#include <boost/signals2.hpp>

//----------------------------------------------------------
typedef boost::signals2::signal<void (int)> VoidSignal;
typedef VoidSignal::slot_type VoidSlot;
struct Listener
{
 void operator () (void)
 { std::cerr<<"operator () (void)"<<std::endl; }
 void operator () (int value)
 { std::cerr<<"operator () (int)"<<std::endl; }
 void operator () (float value)
 { std::cerr<<"operator () (float)"<<std::endl; }
};
//----------------------------------------------------------
int main(int argc,char** argv)
{
 Listener listener;
 VoidSignal sig;
 sig.connect(VoidSlot(boost::bind<void>(listener, _1)));
 sig(15);
 sig(11);
 return 0;
}

если изменить инт на флоат - привязка идет к нужной функции (прелесть xD)

dpt-ru
()
Ответ на: комментарий от dpt-ru

если изменить инт на флоат - привязка идет к нужной функции (прелесть xD)

имею в виду

typedef boost::signals2::signal<void (int)> VoidSignal;

на

typedef boost::signals2::signal<void (float)> VoidSignal;

dpt-ru
()
Ответ на: комментарий от dpt-ru

я тут подумал.. а зачем вообще биндить?

и так работает... у нас же объект-функция...

p.s. я вообще-то уже 4-года как не программирую на плюсах, мне мона иногда и «прогонять»..

#include <iostream>
#include <boost/signals2.hpp>

//----------------------------------------------------------
typedef boost::signals2::signal<void (int)> VoidSignal;
typedef VoidSignal::slot_type VoidSlot;
struct Listener
{
 void operator () (void)
 { std::cerr<<"operator () (void)"<<std::endl; }
 void operator () (int value)
 { std::cerr<<"operator () (int)"<<std::endl; }
 void operator () (float value)
 { std::cerr<<"operator () (float)"<<std::endl; }
};
//----------------------------------------------------------
int main(int argc,char** argv)
{
 Listener listener;
 VoidSignal sig;
 sig.connect(VoidSlot(listener));
 sig(15);
 sig(11);
 return 0;
}
dpt-ru
()
Ответ на: комментарий от dpt-ru

> а зачем вообще биндить?

Для connect, в общем то, можно и не биндить, а вот для disconnect уже придётся передавать функциональный объект. Для симметрии и для того, чтобы разобраться, я и там, и там забиндил оператор.

one_more_hokum ★★★
() автор топика
Ответ на: комментарий от one_more_hokum

а не проще ли хранить коннекш?

// bla-bla-bla
// ...

int main(int argc,char** argv)
{
 Listener listener;
 VoidSignal sig;

 boost::signals2::connection con = sig.connect(VoidSlot(listener));
 sig(15);

 con.disconnect();

 sig(11);
 return 0;
}
dpt-ru
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.