connect() and lambdas

Added by Aaron Wright over 4 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 over 4 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 over 4 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 over 4 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 over 4 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 over 4 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 over 4 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 over 4 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 over 4 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 over 3 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.

(1-9/9)