Hello,

Suppose I am writing an event handler for a push button. The expected
event handler type is a function with one argument of type WMouseEvent.
Often I don't care about the WMouseEvent and would like to pass in
a zero-argument function instead.

If I use bind() to create my handler, such as in the following code, 
then I can simply pass a zero-argument function:


#include <functional>
#include <Wt/WApplication>
#include <Wt/WPushButton>
using namespace Wt;

struct Application : public WApplication
{
    Application(const WEnvironment& env) : WApplication(env)
    {
        WPushButton* button = new WPushButton(root());
        button->clicked().connect(std::bind(&Application::onClicked, this));
    }
    
    void onClicked()
    {
    }
};


(In this example I used the C++11 std::bind(), but it's the same for 
boost::bind() and boost::phoenix::bind()).

This works because the result of a bind() call is a function object
that accepts any number of arguments, and ignores the ones it doesn't 
use. So, even though a zero-argument function was bound and Wt passes
in the WMouseEvent argument, it compiles.

However, if I try to do the same thing with a C++11 lambda, it doesn't
compile:


#include <functional>
#include <Wt/WApplication>
#include <Wt/WPushButton>
using namespace Wt;

struct Application : public WApplication
{
    Application(const WEnvironment& env) : WApplication(env)
    {
        WPushButton* button = new WPushButton(root());
        button->clicked().connect([this]{ this->onClicked(); });
    }
    
    void onClicked()
    {
    }
};


The compiler error is:

In file included from test.cpp:2:
In file included from wt/include/Wt/WApplication:26:
In file included from wt/include/Wt/WCssStyleSheet:14:
In file included from wt/include/Wt/WBreak:10:
In file included from wt/include/Wt/WWebWidget:14:
In file included from wt/include/Wt/WWidget:14:
In file included from wt/include/Wt/WSignal:17:
In file included from boost/signal.hpp:20:
In file included from boost/signals/signal1.hpp:24:
In file included from boost/signals/signal_template.hpp:37:
In file included from boost/function/function1.hpp:11:
In file included from boost/function/detail/maybe_include.hpp:18:
boost/function/function_template.hpp:153:33: error: no matching function for 
call to object of type '<lambda at test.cpp:11:35>'
          BOOST_FUNCTION_RETURN((*f)(BOOST_FUNCTION_ARGS));
                                ^~~~
boost/function/function_template.hpp:75:36: note: expanded from macro 
'BOOST_FUNCTION_RETURN'
#  define BOOST_FUNCTION_RETURN(X) X
                                   ^
boost/function/function_template.hpp:934:53: note: in instantiation of member 
function 'boost::detail::function::void_function_obj_invoker1<<lambda at 
test.cpp:11:35>, void, Wt::WMouseEvent>::invoke' requested here
        { { &manager_type::manage }, &invoker_type::invoke };
                                                    ^
boost/function/function_template.hpp:722:13: note: in instantiation of function 
template specialization 'boost::function1<void, 
Wt::WMouseEvent>::assign_to<<lambda at test.cpp:11:35> >' requested here
      this->assign_to(f);
            ^
boost/signals/slot.hpp:111:24: note: in instantiation of function template 
specialization 'boost::function1<void, Wt::WMouseEvent>::function1<<lambda at 
test.cpp:11:35> >' requested here
    slot(const F& f) : 
slot_function(BOOST_SIGNALS_NAMESPACE::get_invocable_slot(f, 
BOOST_SIGNALS_NAMESPACE::tag_type(f)))
                       ^
wt/include/Wt/WSignal:1021:27: note: in instantiation of function template 
specialization 'boost::slot<boost::function1<void, Wt::WMouseEvent> 
>::slot<<lambda at test.cpp:11:35> >' requested here
  return dynamic_.connect(function, boost::signals::at_front);
                          ^
test.cpp:11:27: note: in instantiation of function template specialization 
'Wt::EventSignal<Wt::WMouseEvent>::connect<<lambda at test.cpp:11:35> >' 
requested here
        button->clicked().connect([this]{ this->onClicked(); });
                          ^
test.cpp:11:35: note: candidate function not viable: requires 0 arguments, but 
1 was provided
        button->clicked().connect([this]{ this->onClicked(); });
                                  ^


The reason this doesn't work is that, unlike the result of bind(),
a lambda is not callable with extra arguments that it ignores.

I think it would be nice if Wt supported passing in a zero-argument
lambda in such a case, just like it supports passing in a zero-
argument bound function.

What do you think? Should I file a ticket for this?

Thanks,
Nate
                                          
------------------------------------------------------------------------------
Own the Future-Intel&reg; Level Up Game Demo Contest 2013
Rise to greatness in Intel's independent game demo contest.
Compete for recognition, cash, and the chance to get your game 
on Steam. $5K grand prize plus 10 genre and skill prizes. 
Submit your demo by 6/6/13. http://p.sf.net/sfu/intel_levelupd2d
_______________________________________________
witty-interest mailing list
witty-interest@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/witty-interest

Reply via email to