Fedyashov's Blog
Just another WordPress.com site
Elegant BOOST_SCOPE_EXIT replacement with auto and lambda from C++0x
The first thing I wanted to do when I saw BOOST_SCOPE / BOOST_SCOPE_EXIT - was to get rid of it. While Boost is good at what it does, implementing similar scoped RAII wrapper with C++0x would yield more elegant, more C++ style solution.
I’m sharing this thought not because of its scientific importance (which is definitely not far from negligible), but:
- to have one more post – as WordPress suggests to “post frequently” ;)
- to practice in presenting some formatted code on WordPress (which is not that easy!)
- more importantly – to get feedback from you in case you see a way to simplify this solution
So here it is:
#include <iostream>
template <typename Lambda>
class continuation
{
public:
explicit continuation(Lambda lambda): lambda_(lambda), active_(false)
{
}
void activate()
{
active_ = true;
}
~continuation()
{
if (active_)
lambda_();
}
private:
continuation(); // not default-constructible
Lambda& lambda_;
bool active_;
};
template<typename T>
continuation<T> create_continuation(T t)
{
return continuation<T>(t);
};
void main()
{
auto ScopeExit = create_continuation([] () { std::cout << "message from continuation ...\n"; });
ScopeExit.activate();
// exiting this scope would invoke the anonymous function...
}
There is some stuff that I would like to get rid of – namely the necessity to use the helper function create_continuation and the need to invoke activate() method against the resulting continuation object. The first problem is that the type of our anonymous function cannot be used directly to parametrize the continuation class. Instead, type is deduced via create_continuation helper function which subsequently is able to instantiate the required continuation object locally – which eventually gets copied back to the caller’s auto variable. And it’s actually the second problem – as the temporary object’s destructor would perform unwanted invoke – which is currently handled with activate() workaround.
Comments and propositions are welcome.
[Update] seems that I missed one important feature of C++0x which is decltype operator. By using it – the sample code above could be rewritten in a more straightforward way so that activate method and create_continuation helper function won’t be required:
void main()
{
auto SomeCode = [] () { std::cout << "message from continuation ...\n"; };
continuation<decltype(SomeCode)> ScopeExit(SomeCode);
// exiting this scope would invoke the anonymous function...
}
Seems like you missed an even bigger simplification: std::function. With std::function you don’t need to template your ScopeExit class. Instead you would simply do
auto ScopeExit([] () { std::cout << "message from continuation …\n"; });
and be done with the whole thing.
Your class would look more like
class continuation
{
public:
explicit continuation(std::function lambda_): lambda_(lambda)
{
}
~continuation()
{
lambda_();
}
private:
continuation(); // not default-constructible
Lambda& lambda_;
};