Re: [Boost-users] [RFC] Signals bound to phoenix functions
On Thursday 24 June 2010 09:31:36 Thomas Heller wrote:
On Wednesday 23 June 2010 18:50:38 Ovanes Markarian wrote:
Stephan, hi!
please see my answer below.
On Wed, Jun 23, 2010 at 5:42 PM, Stephan Menzel
wrote: Unless I want to add something. Unfortunately I can't always take wrap()s output but have to modify a little. In fact, my Queue needs to be templatized as well, modifying the behaviour of the functor. I have a template parameter "Calling". When it is true, another function shall be called by the functor after the method was posted. Now I wanted to do this by phoenix:
template <bool Calling> class Queue {
template<typename Handler>
void post(Handler n_handler) {
m_iosrv.post(n_handler);
};
...
template
boost::signals2::connection connect(boost::signals2::signal<SlotSignature> &n_signal, SlotFunction n_method) {
return n_signal.connect(
if_( CallingBack ) [
post(n_method) , m_signal_callback()
] .else_ [
m_iosrv.wrap( n_method )
] );
};
...
It is difficult to conclude smth from the code without having a self-containing example. But my assumption is that in the 'else'-branch your code does not generate a function object. As far as I can see in the 'if'-branch your code generates a function object using the the comma-operator (if that operator is overloaded in Phoenix), in the 'else'-branch you just have a normal function call, which is not lazy and does not return a function-object.
Phoenix statements always return void. What you want is: phoenix::if_else( CallingBack, /* then functor */, /*else functor */ )
For reference: http://www.boost.org/doc/libs/1_43_0/libs/spirit/phoenix/doc/html/phoenix/c omposite.html#phoenix.composite.operator and http://www.boost.org/doc/libs/1_43_0/libs/spirit/phoenix/doc/html/phoenix/c omposite.html#phoenix.composite.statement (There is a note at the end of that section, for the return value of phoenix statements)
Sorry misunderstood your problem ... The correct answer is: post, m_signal_callback() and m_iosrv.wrap need to be lazy expressions. To achieve that for the first two, you can have a phoenix::function wrapper, for the last one, you can use phoenix::bind (which can be used for the first two as well).
Hi Thomas,
On Thu, Jun 24, 2010 at 11:20 AM, Thomas Heller
The correct answer is: post, m_signal_callback() and m_iosrv.wrap need to be lazy expressions. To achieve that for the first two, you can have a phoenix::function wrapper, for the last one, you can use phoenix::bind (which can be used for the first two as well).
I went for a lazy expression in the meantime, with moderate success.
It works for void() handlers, but as soon as multiple parameters kick
in the originally bound method appears to need additional binding.
I'll have a sample attached.
Here's the lazy function
template <bool CallingBack>
struct slot_wrap_impl {
public:
slot_wrap_impl(Queue<CallingBack> &n_q) : m_q(n_q) {};
template <typename SlotSignature>
struct result {
typedef void type;
};
template <typename SlotSignature>
typename result<SlotSignature>::type
operator()(SlotSignature n_method) const {
using boost::phoenix::if_;
using boost::phoenix::switch_;
using boost::phoenix::case_;
using boost::phoenix::default_;
using boost::phoenix::bind;
std::cout << "binding post...\n";
m_q.post(n_method); // X
std::cout << "post bound" << std::endl;
/*
if (CallingBack) {
m_q.callback();
};
*/
};
private:
Queue<CallingBack> &m_q;
};
I call this in my connector using:
boost::phoenix::function
participants (2)
-
Stephan Menzel
-
Thomas Heller