final WPushButton button = new WPushButton("Click me", this); button.clicked().addListener(this, new Signal.Listener() { public void trigger() { button.setText("Thank you!"); } });
We have been hearing "c++0x is just around the corner" for so many years now that it no longer sounds credible. However, chances are real that some of its goodness is already well supported by your compiler… and Wt !
While there is many things to like about this language revision, the feature I looked most forward to was lambdas. I need to say was, because it is there now, I’ve used it, and I was delighted !
Java can, since long, emulate lambdas (albeit in an overly verbose way) using anonymous inner classes, and this has proven handy (possibly a life-saver) for having a signal/slot implementation in Java, which lacks proper function delegates:
final WPushButton button = new WPushButton("Click me", this); button.clicked().addListener(this, new Signal.Listener() { public void trigger() { button.setText("Thank you!"); } });
Lambdas make life a lot easier when you want to connect small functions to slots. It saves you work for two reasons:
you can define a small anonymous function at the single site where you want to use it, and thus you do not need to touch the header file and decide where to put the implementation, or read the implementation and wonder where it is being used.
you can enclose all your local variables in the function (including this) by copy, and thus do not need to add these as state fields to your class definition. In that way, important state for your widget will stand out!
The best of it: Wt supports lambdas for signal connections since 3.1.0, and you can use this already, at least if your compiler supports it. Most notably, you will need gcc 4.5 or later with -std=c++0x, or Microsoft Visual Studio 2010 for the following to work:
using namespace Wt; WPushButton *button = new WPushButton("Click me", this); button->clicked().connect([=] (const WMouseEvent& e) { button->setText("Thank you!"); });
One slight annoyance is that you need to accept any signal’s arguments (such as a const WMouseEvent& in this case), even if you are not interested in the event details. This was not needed when using the old-style connect syntax since the signals tolerated connecting to functions with less arguments. We are unsure if this annoyance warrants a work-around.
Still, this feature alone makes it worth-while to consider adopting c++0x. Obviously we will not migrate Wt itself to c++0x for years to come, but you can already take advantage of it while using Wt — today !
using std::bind;button->clicked().connect(bind([=]That's it. A minimalistic use of std::bind swallows the argument for you. Of course you can hide it in a template connect() method.
{
button->setText("Thank you!");
}));
using namespace Wt;WPushButton *button = new WPushButton("Click me", this);button->clicked().connect([=] (const WMouseEvent& e)
{
button->setText("Thank you!");
});
using namespace Wt;
using namespace boost.phoenix;WPushButton *button = new WPushButton("Click me", this); button->clicked().connect(bind(&WPushButton::setText, button, "Thank you!"));
button->clicked().connect(setText(button, "Thank you!")); // maybe _setText or setText_
// or so to prevent ambiguity,
// and this will work with
// anything that has a setText member,
// polymorphic or not
using namespace Wt;
using namespace boost.phoenix;WPushButton *button = new WPushButton("Click me", this);
bool someStateThatPersists = false; // might be true later,
// might not... this persists thoughbutton->clicked().connect([&someStateThatPersists, button] (const WMouseEvent& e)
// not sure the syntax is perfectly correct in the [] part...)
{
if(someStateThatPersists)
{
button->setText("Thank you!");
}
else
{
button->setText("Why am I still false?!? Setting myself to true for next time");
someStateThatPersists = true;
}
});
using namespace Wt;
using namespace boost.phoenix;WPushButton *button = new WPushButton("Click me", this);
bool someStateThatPersists = false; // might be true later,
// might not... this persists thoughbutton->clicked().connect(
if_(ref(someStateThatPersists))
[
setText(button, "ThankYou!") // if button does not compile,
// depending on how you made setText,
// you might need to replace it with
// val(button) instead,
// properly made though, this should work.
]
.else
[
setText(button, "Why am I still false?!? Setting myself to true for next time"),
ref(someStateThatPersists)=true
]);