connect() and lambdas
Added by Aaron Wright almost 5 years ago
I'm just getting going with Wt and I have a question about connecting C++11 lambdas to signals. I would like to use a simple lambda with the WApplication::internalPathChanged() signal, but this doesn't work:
internalPathChanged().connect([this](std::string const& path) { setTitle(path); });
I get this error:
error C2064: term does not evaluate to a function taking 6 arguments
So if I add the other arguments, it does work:
internalPathChanged().connect([this](std::string const& path, Wt::NoClass, Wt::NoClass, Wt::NoClass, Wt::NoClass, Wt::NoClass) { setTitle(path); });
But that is obviously pretty goofy. What am I missing from my understanding here?
Replies (9)
RE: connect() and lambdas - Added by adam s almost 5 years ago
You can try to use std::bind to get rid of unused parameters:
internalPathChanged().connect(std::bind([this](std::string const& path) { setTitle(path); }));
RE: connect() and lambdas - Added by Aaron Wright almost 5 years ago
I don't think that is what is going on here. I have defined the parameters; the path is supposed to be the only parameter of the signal. Anyways, what you suggested doesn't compile for me. Does it compile for you?
RE: connect() and lambdas - Added by Aaron Wright almost 5 years ago
So, was this a ridiculous question, are these forums not a good place for questions, or is Wt not very activity developed? (I'm investigating Wt for a commercial product, and lively forums, community,and support are a good thing.)
RE: connect() and lambdas - Added by Bruce Toll almost 5 years ago
Something along these lines should work:
internalPathChanged().connect(std::bind([this] (const std::string &new_path) { log("log") << "internalPathChanged(), new_path = '" << new_path << "'"; }, std::placeholders::_1));
As a resource, the examples subdirectory is a good supplement to the Wt documentation. The examples/widgetgallery subdirectory, in particular, highlights C++11 features, including the use of lambdas with connect. An example with a lambda parameter can be found in examples/widgetgallery/examples/Image.cpp.
RE: connect() and lambdas - Added by Aaron Wright almost 5 years ago
You're right, but I'm still not understanding what the difference between these two following statements, and why one compiles and the other doesn't.
This doesn't compile:
internalPathChanged().connect([](std::string const& path) { std::cout << path << std::endl; });
This does compile:
button->clicked().connect([](Wt::WMouseEvent const& e) { std::cout << "pushed" << std::endl; });
Why does one require extra awkwardness, and the other doesn't? Is this on purpose, or is this an oversight?
RE: connect() and lambdas - Added by Bruce Toll almost 5 years ago
The connect() methods for Wt::Signal and Wt::EventSignal accept different arguments. There is some historical background in the issue tracker (search for lambda). You may also find this blog post of interest: http://www.webtoolkit.eu/wt/blog/2015/09/30/wt_4_reflections/more.
RE: connect() and lambdas - Added by Koen Deforche almost 5 years ago
Indeed, you need std::bind(). You will be able to get rid of std::bind() in case you are not 'ignoring' signal arguments in your slot in Wt4 (which uses a c++11 variadic template signal implementation).
RE: connect() and lambdas - Added by Aaron Wright almost 5 years ago
Koen, I am not ignoring any signal arguments in the internalPathChanged() case, that I know of; unless you count the NoClass arguments. clicked() doesn't seem to suffer from the same problem.
Bruce, I did not notice that they were different types of signals. Thanks for that tip. I'm not sure why that would lead to a different API between two seemingly similar connect() functions, but it gives me something to research more.
RE: connect() and lambdas - Added by Vincenzo Romano about 4 years ago
Maybe the documentation for the actual signal arguments would also help a lot.
I am also willing to get rid of std:bind, even in Wt3, but the documentation is buried within the C implementation code.