The simplest and neatest c++11 ScopeGuard - c++

I'm attempting to write a simple ScopeGuard based on Alexandrescu concepts but with c++11 idioms.
namespace RAII
{
template< typename Lambda >
class ScopeGuard
{
mutable bool committed;
Lambda rollbackLambda;
public:
ScopeGuard( const Lambda& _l) : committed(false) , rollbackLambda(_l) {}
template< typename AdquireLambda >
ScopeGuard( const AdquireLambda& _al , const Lambda& _l) : committed(false) , rollbackLambda(_l)
{
_al();
}
~ScopeGuard()
{
if (!committed)
rollbackLambda();
}
inline void commit() const { committed = true; }
};
template< typename aLambda , typename rLambda>
const ScopeGuard< rLambda >& makeScopeGuard( const aLambda& _a , const rLambda& _r)
{
return ScopeGuard< rLambda >( _a , _r );
}
template<typename rLambda>
const ScopeGuard< rLambda >& makeScopeGuard(const rLambda& _r)
{
return ScopeGuard< rLambda >(_r );
}
}
Here is the usage:
void SomeFuncThatShouldBehaveAtomicallyInCaseOfExceptions()
{
std::vector<int> myVec;
std::vector<int> someOtherVec;
myVec.push_back(5);
//first constructor, adquire happens elsewhere
const auto& a = RAII::makeScopeGuard( [&]() { myVec.pop_back(); } );
//sintactically neater, since everything happens in a single line
const auto& b = RAII::makeScopeGuard( [&]() { someOtherVec.push_back(42); }
, [&]() { someOtherVec.pop_back(); } );
b.commit();
a.commit();
}
Since my version is way shorter than most examples out there (like Boost ScopeExit) i'm wondering what specialties i'm leaving out. Hopefully i'm in a 80/20 scenario here (where i got 80 percent of neatness with 20 percent of lines of code), but i couldn't help but wonder if i'm missing something important, or is there some shortcoming worth mentioning of this version of the ScopeGuard idiom
thanks!
Edit I noticed a very important issue with the makeScopeGuard that takes the adquire lambda in the constructor. If the adquire lambda throws, then the release lambda is never called, because the scope guard was never fully constructed. In many cases, this is the desired behavior, but i feel that sometimes a version that will invoke rollback if a throw happens is desired as well:
//WARNING: only safe if adquire lambda does not throw, otherwise release lambda is never invoked, because the scope guard never finished initialistion..
template< typename aLambda , typename rLambda>
ScopeGuard< rLambda > // return by value is the preferred C++11 way.
makeScopeGuardThatDoesNOTRollbackIfAdquireThrows( aLambda&& _a , rLambda&& _r) // again perfect forwarding
{
return ScopeGuard< rLambda >( std::forward<aLambda>(_a) , std::forward<rLambda>(_r )); // *** no longer UB, because we're returning by value
}
template< typename aLambda , typename rLambda>
ScopeGuard< rLambda > // return by value is the preferred C++11 way.
makeScopeGuardThatDoesRollbackIfAdquireThrows( aLambda&& _a , rLambda&& _r) // again perfect forwarding
{
auto scope = ScopeGuard< rLambda >(std::forward<rLambda>(_r )); // *** no longer UB, because we're returning by value
_a();
return scope;
}
so for completeness, i want to put in here the complete code, including tests:
#include <vector>
namespace RAII
{
template< typename Lambda >
class ScopeGuard
{
bool committed;
Lambda rollbackLambda;
public:
ScopeGuard( const Lambda& _l) : committed(false) , rollbackLambda(_l) {}
ScopeGuard( const ScopeGuard& _sc) : committed(false) , rollbackLambda(_sc.rollbackLambda)
{
if (_sc.committed)
committed = true;
else
_sc.commit();
}
ScopeGuard( ScopeGuard&& _sc) : committed(false) , rollbackLambda(_sc.rollbackLambda)
{
if (_sc.committed)
committed = true;
else
_sc.commit();
}
//WARNING: only safe if adquire lambda does not throw, otherwise release lambda is never invoked, because the scope guard never finished initialistion..
template< typename AdquireLambda >
ScopeGuard( const AdquireLambda& _al , const Lambda& _l) : committed(false) , rollbackLambda(_l)
{
std::forward<AdquireLambda>(_al)();
}
//WARNING: only safe if adquire lambda does not throw, otherwise release lambda is never invoked, because the scope guard never finished initialistion..
template< typename AdquireLambda, typename L >
ScopeGuard( AdquireLambda&& _al , L&& _l) : committed(false) , rollbackLambda(std::forward<L>(_l))
{
std::forward<AdquireLambda>(_al)(); // just in case the functor has &&-qualified operator()
}
~ScopeGuard()
{
if (!committed)
rollbackLambda();
}
inline void commit() { committed = true; }
};
//WARNING: only safe if adquire lambda does not throw, otherwise release lambda is never invoked, because the scope guard never finished initialistion..
template< typename aLambda , typename rLambda>
ScopeGuard< rLambda > // return by value is the preferred C++11 way.
makeScopeGuardThatDoesNOTRollbackIfAdquireThrows( aLambda&& _a , rLambda&& _r) // again perfect forwarding
{
return ScopeGuard< rLambda >( std::forward<aLambda>(_a) , std::forward<rLambda>(_r )); // *** no longer UB, because we're returning by value
}
template< typename aLambda , typename rLambda>
ScopeGuard< rLambda > // return by value is the preferred C++11 way.
makeScopeGuardThatDoesRollbackIfAdquireThrows( aLambda&& _a , rLambda&& _r) // again perfect forwarding
{
auto scope = ScopeGuard< rLambda >(std::forward<rLambda>(_r )); // *** no longer UB, because we're returning by value
_a();
return scope;
}
template<typename rLambda>
ScopeGuard< rLambda > makeScopeGuard(rLambda&& _r)
{
return ScopeGuard< rLambda >( std::forward<rLambda>(_r ));
}
namespace basic_usage
{
struct Test
{
std::vector<int> myVec;
std::vector<int> someOtherVec;
bool shouldThrow;
void run()
{
shouldThrow = true;
try
{
SomeFuncThatShouldBehaveAtomicallyInCaseOfExceptionsUsingScopeGuardsThatDoesNOTRollbackIfAdquireThrows();
} catch (...)
{
AssertMsg( myVec.size() == 0 && someOtherVec.size() == 0 , "rollback did not work");
}
shouldThrow = false;
SomeFuncThatShouldBehaveAtomicallyInCaseOfExceptionsUsingScopeGuardsThatDoesNOTRollbackIfAdquireThrows();
AssertMsg( myVec.size() == 1 && someOtherVec.size() == 1 , "unexpected end state");
shouldThrow = true;
myVec.clear(); someOtherVec.clear();
try
{
SomeFuncThatShouldBehaveAtomicallyInCaseOfExceptionsUsingScopeGuardsThatDoesRollbackIfAdquireThrows();
} catch (...)
{
AssertMsg( myVec.size() == 0 && someOtherVec.size() == 0 , "rollback did not work");
}
}
void SomeFuncThatShouldBehaveAtomicallyInCaseOfExceptionsUsingScopeGuardsThatDoesNOTRollbackIfAdquireThrows() //throw()
{
myVec.push_back(42);
auto a = RAII::makeScopeGuard( [&]() { HAssertMsg( myVec.size() > 0 , "attempt to call pop_back() in empty myVec"); myVec.pop_back(); } );
auto b = RAII::makeScopeGuardThatDoesNOTRollbackIfAdquireThrows( [&]() { someOtherVec.push_back(42); }
, [&]() { HAssertMsg( myVec.size() > 0 , "attempt to call pop_back() in empty someOtherVec"); someOtherVec.pop_back(); } );
if (shouldThrow) throw 1;
b.commit();
a.commit();
}
void SomeFuncThatShouldBehaveAtomicallyInCaseOfExceptionsUsingScopeGuardsThatDoesRollbackIfAdquireThrows() //throw()
{
myVec.push_back(42);
auto a = RAII::makeScopeGuard( [&]() { HAssertMsg( myVec.size() > 0 , "attempt to call pop_back() in empty myVec"); myVec.pop_back(); } );
auto b = RAII::makeScopeGuardThatDoesRollbackIfAdquireThrows( [&]() { someOtherVec.push_back(42); if (shouldThrow) throw 1; }
, [&]() { HAssertMsg( myVec.size() > 0 , "attempt to call pop_back() in empty someOtherVec"); someOtherVec.pop_back(); } );
b.commit();
a.commit();
}
};
}
}

Even shorter: I don't know why you guys insist on putting the template on the guard class.
#include <functional>
class scope_guard {
public:
template<class Callable>
scope_guard(Callable && undo_func) try : f(std::forward<Callable>(undo_func)) {
} catch(...) {
undo_func();
throw;
}
scope_guard(scope_guard && other) : f(std::move(other.f)) {
other.f = nullptr;
}
~scope_guard() {
if(f) f(); // must not throw
}
void dismiss() noexcept {
f = nullptr;
}
scope_guard(const scope_guard&) = delete;
void operator = (const scope_guard&) = delete;
private:
std::function<void()> f;
};
Note that it is essential that the cleanup code does not throw, otherwise you get in similar situations as with throwing destructors.
Usage:
// do step 1
step1();
scope_guard guard1 = [&]() {
// revert step 1
revert1();
};
// step 2
step2();
guard1.dismiss();
My inspiration was the same DrDobbs article as for the OP.
Edit 2017/2018: After watching (some of) Andrei's presentation that André linked to (I skipped to the end where it said "Painfully Close to Ideal!") I realized that it's doable. Most of the time you don't want to have extra guards for everything. You just do stuff, and in the end it either succeeds or rollback should happen.
Edit 2018: Added execution policy which removed the necessity of the dismiss call.
#include <functional>
#include <deque>
class scope_guard {
public:
enum execution { always, no_exception, exception };
scope_guard(scope_guard &&) = default;
explicit scope_guard(execution policy = always) : policy(policy) {}
template<class Callable>
scope_guard(Callable && func, execution policy = always) : policy(policy) {
this->operator += <Callable>(std::forward<Callable>(func));
}
template<class Callable>
scope_guard& operator += (Callable && func) try {
handlers.emplace_front(std::forward<Callable>(func));
return *this;
} catch(...) {
if(policy != no_exception) func();
throw;
}
~scope_guard() {
if(policy == always || (std::uncaught_exception() == (policy == exception))) {
for(auto &f : handlers) try {
f(); // must not throw
} catch(...) { /* std::terminate(); ? */ }
}
}
void dismiss() noexcept {
handlers.clear();
}
private:
scope_guard(const scope_guard&) = delete;
void operator = (const scope_guard&) = delete;
std::deque<std::function<void()>> handlers;
execution policy = always;
};
Usage:
scope_guard scope_exit, scope_fail(scope_guard::execution::exception);
action1();
scope_exit += [](){ cleanup1(); };
scope_fail += [](){ rollback1(); };
action2();
scope_exit += [](){ cleanup2(); };
scope_fail += [](){ rollback2(); };
// ...

Boost.ScopeExit is a macro that needs to work with non-C++11 code, i.e. code that has no access to lambdas in the language. It uses some clever template hacks (like abusing the ambiguity that arises from using < for both templates and comparison operators!) and the preprocessor to emulate lambda features. That's why the code is longer.
The code shown is also buggy (which is probably the strongest reason to use an existing solution): it invokes undefined behaviour due to returning references to temporaries.
Since you're trying to use C++11 features, the code could be improved a lot by using move semantics, rvalue references and perfect-forwarding:
template< typename Lambda >
class ScopeGuard
{
bool committed; // not mutable
Lambda rollbackLambda;
public:
// make sure this is not a copy ctor
template <typename L,
DisableIf<std::is_same<RemoveReference<RemoveCv<L>>, ScopeGuard<Lambda>>> =_
>
/* see http://loungecpp.net/w/EnableIf_in_C%2B%2B11
* and http://stackoverflow.com/q/10180552/46642 for info on DisableIf
*/
explicit ScopeGuard(L&& _l)
// explicit, unless you want implicit conversions from *everything*
: committed(false)
, rollbackLambda(std::forward<L>(_l)) // avoid copying unless necessary
{}
template< typename AdquireLambda, typename L >
ScopeGuard( AdquireLambda&& _al , L&& _l) : committed(false) , rollbackLambda(std::forward<L>(_l))
{
std::forward<AdquireLambda>(_al)(); // just in case the functor has &&-qualified operator()
}
// move constructor
ScopeGuard(ScopeGuard&& that)
: committed(that.committed)
, rollbackLambda(std::move(that.rollbackLambda)) {
that.committed = true;
}
~ScopeGuard()
{
if (!committed)
rollbackLambda(); // what if this throws?
}
void commit() { committed = true; } // no need for const
};
template< typename aLambda , typename rLambda>
ScopeGuard< rLambda > // return by value is the preferred C++11 way.
makeScopeGuard( aLambda&& _a , rLambda&& _r) // again perfect forwarding
{
return ScopeGuard< rLambda >( std::forward<aLambda>(_a) , std::forward<rLambda>(_r )); // *** no longer UB, because we're returning by value
}
template<typename rLambda>
ScopeGuard< rLambda > makeScopeGuard(rLambda&& _r)
{
return ScopeGuard< rLambda >( std::forward<rLambda>(_r ));
}

You might be interested in seeing this presentation by Andrei himself on his own taken on how to improve scopedguard with c++11

You can use std::unique_ptr for that purpose which implements the RAII pattern.
For example:
vector<int> v{};
v.push_back(42);
unique_ptr<decltype(v), function<void(decltype(v)*)>>
p{&v, [] (decltype(v)* v) { if (uncaught_exception()) { v->pop_back(); }}};
throw exception(); // rollback
p.release(); // explicit commit
The deleter function from the unique_ptr p rolls the formerly inserted value back, if the scope was left while an exception is active. If you prefer an explicit commit, you can remove the uncaugth_exception() question in the deleter function and add at the end of the block p.release() which releases the pointer. See Demo here.

I use this works like a charm, no extra code.
shared_ptr<int> x(NULL, [&](int *) { CloseResource(); });

There's a chance this approach will be standardized in C++17 or in the Library Fundamentals TS through proposal P0052R0
template <typename EF>
scope_exit<see below> make_scope_exit(EF &&exit_function) noexcept;
template <typename EF>
scope_exit<see below> make_scope_fail(EF && exit_function) noexcept;
template <typename EF>
scope_exit<see below> make_scope_success(EF && exit_function) noexcept;
On first glance this has the same caveat as std::async because you have to store the return value or the destructor will be called immediately and it won't work as expected.

Most of the other solutions involve a move of a lambda, e.g. by using the lambda argument to initialize a std::function or an object of type deduced from the lambda.
Here's one that is quite simple, and allows using a named lambda without moving it (requires C++17):
template<typename F>
struct OnExit
{
F func;
OnExit(F&& f): func(std::forward<F>(f)) {}
~OnExit() { func(); }
};
template<typename F> OnExit(F&& frv) -> OnExit<F>;
int main()
{
auto func = []{ };
OnExit x(func); // No move, F& refers to func
OnExit y([]{}); // Lambda is moved to F.
}
The deduction guide makes F deduce as lvalue reference when the argument is an lvalue.

Without commitment tracking, but extremely neat and fast.
template <typename F>
struct ScopeExit {
ScopeExit(F&& f) : m_f(std::forward<F>(f)) {}
~ScopeExit() { m_f(); }
F m_f;
};
template <typename F>
ScopeExit<F> makeScopeExit(F&& f) {
return ScopeExit<F>(std::forward<F>(f));
};
#define STRING_JOIN(arg1, arg2) STRING_JOIN2(arg1, arg2)
#define STRING_JOIN2(arg1, arg2) arg1 ## arg2
#define ON_SCOPE_EXIT(code) auto STRING_JOIN(scopeExit, __LINE__) = makeScopeExit([&](){code;})
Usage
{
puts("a");
auto _ = makeScopeExit([]() { puts("b"); });
// More readable with a macro
ON_SCOPE_EXIT(puts("c"));
} # prints a, c, b

makeScopeGuard returns a const reference. You can't store this const reference in a const ref at the caller's side in a line like:
const auto& a = RAII::makeScopeGuard( [&]() { myVec.pop_back(); } );
So you are invoking undefined behaviour.
Herb Sutter GOTW 88 gives some background about storing values in const references.

FWIW I think that Andrei Alexandrescu has used a pretty neat syntax in his CppCon 2015's talk about "Declarative Control Flow" (video, slides).
The following code is heavily inspired by it:
Try It Online
GitHub Gist
#include <iostream>
#include <type_traits>
#include <utility>
using std::cout;
using std::endl;
template <typename F>
struct ScopeExitGuard
{
public:
struct Init
{
template <typename G>
ScopeExitGuard<typename std::remove_reference<G>::type>
operator+(G&& onScopeExit_)
{
return {false, std::forward<G>(onScopeExit_)};
}
};
private:
bool m_callOnScopeExit = false;
mutable F m_onScopeExit;
public:
ScopeExitGuard() = delete;
template <typename G> ScopeExitGuard(const ScopeExitGuard<G>&) = delete;
template <typename G> void operator=(const ScopeExitGuard<G>&) = delete;
template <typename G> void operator=(ScopeExitGuard<G>&&) = delete;
ScopeExitGuard(const bool callOnScopeExit_, F&& onScopeExit_)
: m_callOnScopeExit(callOnScopeExit_)
, m_onScopeExit(std::forward<F>(onScopeExit_))
{}
template <typename G>
ScopeExitGuard(ScopeExitGuard<G>&& other)
: m_callOnScopeExit(true)
, m_onScopeExit(std::move(other.m_onScopeExit))
{
other.m_callOnScopeExit = false;
}
~ScopeExitGuard()
{
if (m_callOnScopeExit)
{
m_onScopeExit();
}
}
};
#define ON_SCOPE_EXIT_GUARD_VAR_2(line_num) _scope_exit_guard_ ## line_num ## _
#define ON_SCOPE_EXIT_GUARD_VAR(line_num) ON_SCOPE_EXIT_GUARD_VAR_2(line_num)
// usage
// ON_SCOPE_EXIT <callable>
//
// example
// ON_SCOPE_EXIT [] { cout << "bye" << endl; };
#define ON_SCOPE_EXIT \
const auto ON_SCOPE_EXIT_GUARD_VAR(__LINE__) \
= ScopeExitGuard<void*>::Init{} + /* the trailing '+' is the trick to the call syntax ;) */
int main()
{
ON_SCOPE_EXIT [] {
cout << "on scope exit 1" << endl;
};
ON_SCOPE_EXIT [] {
cout << "on scope exit 2" << endl;
};
cout << "in scope" << endl; // "in scope"
}
// "on scope exit 2"
// "on scope exit 1"
For your usecase, you might also be interested in std::uncaught_exception() and std::uncaught_exceptions() to know whether your exiting the scope "normally" or after an exception has been thrown:
ON_SCOPE_EXIT [] {
if (std::uncaught_exception()) {
cout << "an exception has been thrown" << endl;
}
else {
cout << "we're probably ok" << endl;
}
};
HTH

Here is one I came up with in C++17. It is trivial to port it to C++11 and/or add deactivation option:
template<class F>
struct scope_guard
{
F f_;
~scope_guard() { f_(); }
};
template<class F> scope_guard(F) -> scope_guard<F>;
Usage:
void foo()
{
scope_guard sg1{ []{...} };
auto sg2 = scope_guard{ []{...} };
}
Edit: In same key here is the guard that goes off only "on exception":
#include <exception>
template<class F>
struct xguard
{
F f_;
int count_ = std::uncaught_exceptions();
~xguard() { if (std::uncaught_exceptions() != count_) f_(); }
};
template<class F> xguard(F) -> xguard<F>;
Usage:
void foobar()
{
xguard xg{ []{...} };
...
// no need to deactivate if everything is good
xguard{ []{...} }, // will go off only if foo() or bar() throw
foo(),
bar();
// 2nd guard is no longer alive here
}

Here's another one, now a variation on #kwarnke's:
std::vector< int > v{ };
v.push_back( 42 );
std::shared_ptr< void > guard( nullptr , [ & v ] ( auto )
{
v.pop_back( );
} );

You already chosen an answer, but I'll take the challenge anyway:
#include <iostream>
#include <type_traits>
#include <utility>
template < typename RollbackLambda >
class ScopeGuard;
template < typename RollbackLambda >
auto make_ScopeGuard( RollbackLambda &&r ) -> ScopeGuard<typename
std::decay<RollbackLambda>::type>;
template < typename RollbackLambda >
class ScopeGuard
{
// The input may have any of: cv-qualifiers, l-value reference, or both;
// so I don't do an exact template match. I want the return to be just
// "ScopeGuard," but I can't figure it out right now, so I'll make every
// version a friend.
template < typename AnyRollbackLambda >
friend
auto make_ScopeGuard( AnyRollbackLambda && ) -> ScopeGuard<typename
std::decay<AnyRollbackLambda>::type>;
public:
using lambda_type = RollbackLambda;
private:
// Keep the lambda, of course, and if you really need it at the end
bool committed;
lambda_type rollback;
// Keep the main constructor private so regular creation goes through the
// external function.
explicit ScopeGuard( lambda_type rollback_action )
: committed{ false }, rollback{ std::move(rollback_action) }
{}
public:
// Do allow moves
ScopeGuard( ScopeGuard &&that )
: committed{ that.committed }, rollback{ std::move(that.rollback) }
{ that.committed = true; }
ScopeGuard( ScopeGuard const & ) = delete;
// Cancel the roll-back from being called.
void commit() { committed = true; }
// The magic happens in the destructor.
// (Too bad that there's still no way, AFAIK, to reliably check if you're
// already in exception-caused stack unwinding. For now, we just hope the
// roll-back doesn't throw.)
~ScopeGuard() { if (not committed) rollback(); }
};
template < typename RollbackLambda >
auto make_ScopeGuard( RollbackLambda &&r ) -> ScopeGuard<typename
std::decay<RollbackLambda>::type>
{
using std::forward;
return ScopeGuard<typename std::decay<RollbackLambda>::type>{
forward<RollbackLambda>(r) };
}
template < typename ActionLambda, typename RollbackLambda >
auto make_ScopeGuard( ActionLambda && a, RollbackLambda &&r, bool
roll_back_if_action_throws ) -> ScopeGuard<typename
std::decay<RollbackLambda>::type>
{
using std::forward;
if ( not roll_back_if_action_throws ) forward<ActionLambda>(a)();
auto result = make_ScopeGuard( forward<RollbackLambda>(r) );
if ( roll_back_if_action_throws ) forward<ActionLambda>(a)();
return result;
}
int main()
{
auto aa = make_ScopeGuard( []{std::cout << "Woah" << '\n';} );
int b = 1;
try {
auto bb = make_ScopeGuard( [&]{b *= 2; throw b;}, [&]{b = 0;}, true );
} catch (...) {}
std::cout << b++ << '\n';
try {
auto bb = make_ScopeGuard( [&]{b *= 2; throw b;}, [&]{b = 0;}, false );
} catch (...) {}
std::cout << b++ << '\n';
return 0;
}
// Should write: "0", "2", and "Woah" in that order on separate lines.
Instead of having creation functions and a constructor, you limited to just the creation functions, with the main constructor being private. I couldn't figure out how to limit the friend-ed instantiations to just the ones involving the current template parameter. (Maybe because the parameter is mentioned only in the return type.) Maybe a fix to that can be asked on this site. Since the first action doesn't need to be stored, it's present only in the creation functions. There's a Boolean parameter to flag if throwing from the first action triggers a roll-back or not.
The std::decay part strips both cv-qualifiers and reference markers. But you can't use it for this general purpose if the input type is a built-in array, since it'll apply the array-to-pointer conversion too.

Yet another answer, but I am afraid I find the others all lacking in one way or another. Notably, the accepted answer dates from 2012, but it has an important bug (see this comment). This shows the importance of testing.
Here is an implementation of a >=C++11 scope_guard that is openly available and extensively tested. It is meant to be/have:
modern, elegant, simple (mostly single-function interface and no macros)
general (accepts any callable that respects preconditions)
carefully documented
thin callback wrapping (no added std::function or virtual table penalties)
proper exception specifications
See also the full list of features.

Related

Using lambdas to throw template type's member as an exception

Here is a simple version of a use case that I have been trying to investigate
#include<iostream>
#include<stdexcept>
#include<memory>
#include<type_traits>
#include<string>
class intexception:public std::exception
{
public:
intexception(std::string m,int x):msg(m),g(x){}
const char* what() const throw() { return msg.c_str(); }
virtual ~intexception() throw(){}
int getExceptInt()const { return g;}
private:
std::string msg;
int g;
};
class Int
{
public:
Int():m_ptr(nullptr){}
Int(const int& x) : m_ptr(new int(x)) { }
Int(const Int& in) : m_ptr( (in.get()) ? ( new int(*in.m_ptr) ) : ( nullptr ) ) {}
Int& operator=(const Int&) = default;
Int(Int&&) = default;
Int& operator=(Int&&) = default;
int get() const { return *m_ptr; }
private:
std::unique_ptr<int>m_ptr;
};
class TypedInt
{
public:
template<typename T,
typename std::enable_if< std::is_same<typename std::decay<T>::type,int>::value || std::is_same<typename std::decay<T>::type,long>::value,
std::nullptr_t>::type = nullptr>
explicit TypedInt (T& intid )
: m_holder( intid ),
m_throw ( [this]() { throw intexception("Integer Exception",static_cast<T>(this->get())); } )
{}
TypedInt():m_holder(),m_throw(std::function<void()>()){}
TypedInt& operator=(TypedInt&&) = default;
TypedInt(TypedInt&& other):m_holder(std::move(other.m_holder)),m_throw(std::move(other.m_throw)) {}
TypedInt& operator=(const TypedInt&) = default;
TypedInt(const TypedInt&) = default;
int get() const { return m_holder.get(); }
void Throw() { m_throw(); }
private:
Int m_holder;
std::function<void()>m_throw;
};
void testThrow(TypedInt t)
{
try
{
t.Throw();
}
catch(const intexception& e)
{
std::cout<<e.what()<<std::endl;
std::cout<<e.getExceptInt()<<std::endl;
}
}
int main()
{
int z = 10;
TypedInt t1(z);
TypedInt t2;
t2 = std::move(t1);
testThrow(std::move(t2));
return 0;
}
This compiles fine without problems. However, it ends up in a segmentation fault.
I looked at this link and I feel I might be facing a similar problem.
I have debugged this with gdb and I cant understand as to why this get() function is returning a null value for underlying integer in my std::unique_ptr member variable.
When you construct t1, you construct its m_throw with:
m_throw ([this]() {
throw intexception("Integer Exception",static_cast<T>(this->get()));
})
That is, t1.m_throw is holding onto t1 (by pointer). It's throwing an intexception that is constructed from t1.m_holder.get().
When you move that into t2 - the actual underlying lambda in the std::function doesn't change. It's still trying to throw t1.m_holder.get(). The problem is, once you moved from t1.m_holder , dereferencing that underlying unique_ptr is invalid - which is the source of your segmentation fault.
You'll have to rebind the thrower to make sure that you're always throwing from this. The easiest would just be to pass in the TypedInt instance as an argument, then you don't have to worry about anything.
You capture the this by value in the lambda. After all the moves, the this pointer you captured no longer points to a valid object.
The this capture does not "track" the object it is captured for.
You can try simply the implementation to capture the intid instead.
m_throw ( [intid]() {
throw intexception("Integer Exception", static_cast<int>(intid));
} )
Else; if the lambda is required to use the current object, the this pointer could be passed in as an argument when the lambda is called. In this case the lambda seems "heavy" given the use case.
The best be to avoid the lambda and simply throw when required; with the values in the objects at the time of the throw.

Call a function before function exits

I will begin with an example. Suppose I need to guard a code with a function inside a mutex. There are two ways of implementing this.
#include <iostream>
#include <vector>
#include <pthread.h>
pthread_mutex_t myMutex = PTHREAD_MUTEX_INITIALIZER;
std::vector<float> myVec;
void threadfunc(int i, float value)
{
pthread_mutex_lock(&myMutex);
if(i <= 0 || i > myVec.size())
{
pthread_mutex_unlock(&myMutex);
return;
}
if(value < 0)
{
pthread_mutex_unlock(&myMutex);
return;
}
myVec[i] += value;
pthread_mutex_unlock(&myMutex);
return;
}
class AUTOMUTEX
{
private:
pthread_mutex_t *mMutex;
public:
AUTOMUTEX(pthread_mutex_t *mutex): mMutex(mutex)
{
pthread_mutex_lock(mMutex);
}
~AUTOMUTEX()
{
pthread_mutex_unlock(mMutex);
}
};
void threadfunc_autolock(int i, float value)
{
AUTOMUTEX autoMutex(&myMutex);
if(i <= 0 || i > myVec.size())
{
return;
}
if(value < 0)
{
return;
}
myVec[i] += value;
return;
}
int main()
{
threadfunc_autolock(5, 10);
threadfunc(0, 7);
return 1;
}
As it is clear from the example threadfunc autolock is better implementation as calling pthread_mutex_unlock function return is taken care by destructor call to AUTOMUTEX (C++ 11 thread has support for this. So we don't need our own implementation of AUTOMUTEX if we are using C++11 thread library).
Is there a way we can achieve this without implementing a wrapper class each time we need to do this with some set/reset function pair. Does boost or C++ 11 have some predefined template class with which we can achieve the behaviour of AUTOMUTEX for any such "set/reset" sort of function. This is really helpful for functions with multiple points of return.
In other words does boost/C++ provide a class with the following behaviour.
//sample code not compilable.
template <class T, class Y>
class myAuto
{
myAuto()
{
T();
}
~myAuto()
{
Y();
};
You may write your own geneirc RAII class, something like:
class Finally
{
public:
explicit Finally(std::function<void()> f) : mF(f) {}
~Finally() noexcept() {
try
{
mF();
} catch (...) {
// Handle error.
}
}
Finally(const Finally&) = delete;
Finally(Finally&&) = delete;
Finally& operator=(const Finally&) = delete;
Finally& operator=(Finally&&) = delete;
private:
std::function<void()> mF;
};
Usage:
{
pthread_mutex_lock(&myMutex);
Finally finally([&](){ pthread_mutex_unlock(&myMutex); });
//..
}
Even if a dedicated RAII object may be more appropriate in some case (as Mutex).
There is a proposal for a generic scope guard to be included in the next C++ standard, and I think it is accepted. You can find an implementation here, together with a link to the reference paper.
In principle, it is similar to the classical ScopeGuard, but it also provides some special cases e.g. for C-like file APIs.
You could use something like ScopeGuard. (Now somewhat old-fashioned.)
But given how easy and clear it is to construct a specific RAII wrapper for each resource type I would normally do that.
(I don't think boost ever adopted anything like ScopeGuard. With std::function, lambdas and so on it's easy to do your own.)
What's wrong with writing your own generic resource wrapper?
template <typename Res, typename Fn = std::function<void(Res*)>>
class resource_mgr
{
Res* resource;
Fn initialize, finalize;
public:
resource_mgr (Res* r, Fn i, Fn f)
: resource(r),
initialize(i),
finalize(f)
{
initialize(resource);
}
resource_mgr (resource_mgr const&) = delete;
resource_mgr (resource_mgr&&) = delete;
resource_mgr const& operator = (resource_mgr const&) = delete;
resource_mgr const& operator = (resource_mgr&&) = delete;
~resource_mgr
{
try
{
finalize(resource);
}
catch(...)
{
std::cerr << "Uh-oh!"
}
}
};
You can keep it simple or go wild on something like this -- use smart pointers, define move operations, add support for custom error handlers, etc. You might use it like this:
void threadfunc_autolock(int i, float value)
{
resource_mgr<mutex_t> autoMutex (
&myMutex,
[](auto* p) { if (!pthread_mutex_lock(p)) throw Something(); },
[](auto* p) { if (!pthread_mutex_unlock(p)) throw Something(); }
);
/* . . . */
}
Here's an example using Boost.ScopeExit (untested):
#include <boost/scope_exit.hpp>
...
void threadfunc_autolock(int i, float value)
{
pthread_mutex_lock(&myMutex);
BOOST_SCOPE_EXIT(&myMutex) {
pthread_mutex_unlock(&myMutex);
} BOOST_SCOPE_EXIT_END
if(i <= 0 || i > myVec.size())
{
return;
}
if(value < 0)
{
return;
}
myVec[i] += value;
}

c++11 : Compare lambda expression

Imagine have the following class :
#include <functional>
#include <vector>
template<typename T1> class Signaler
{
public:
typedef std::function<void (T1)> Func;
public:
Signaler()
{
}
void Call(T1 arg)
{
for(Int32 i = (Int32)_handlers.size() - 1; i > -1; i--)
{
Func handler = _handlers[i];
handler(arg);
}
}
Signaler& operator+=(Func f)
{
_handlers.push_back( f );
return *this;
}
Signaler& operator-=(Func f)
{
for(auto i = _handlers.begin(); i != _handlers.end(); i++)
{
if ( (*i).template target<void (T1)>() == f.template target<void (T1)>() )
{
_handlers.erase( i );
break;
}
}
return *this;
}
private:
std::vector<Func> _handlers;
};
And I use it the following way :
Signaler Global::Signal_SelectionChanged;
class C1
{
public:
void Register()
{
Global::Signal_SelectionChanged += [&](SelectionChangedEventArgs* e) { this->selectionChangedEvent_cb(e); };
}
void Unregister()
{
Global::Signal_SelectionChanged -= [&](SelectionChangedEventArgs* e) { this->selectionChangedEvent_cb(e); };
}
void selectionChangedEvent_cb(SelectionChangedEventArgs* e) {}
};
class C2
{
public:
void Register()
{
Global::Signal_SelectionChanged += [&](SelectionChangedEventArgs* e) { this->selectionChangedEvent_cb(e); };
}
void Unregister()
{
Global::Signal_SelectionChanged -= [&](SelectionChangedEventArgs* e) { this->selectionChangedEvent_cb(e); };
}
void selectionChangedEvent_cb(SelectionChangedEventArgs* e) {}
};
Now, the problem that I have is when I call 'Unregister' from the class C2, it removes the wrong version of the 'lambda" expression, because the 'lambda' looks similar.
How can I solve this problem ?
Any idea ?
Thanks
The problem is that you are using std::function::target with a type that is not the type of the object stored in the std::function, so it is returning a null pointer. That is, you need to know the actual type of the object stored in the std::function to be able to call target.
Even if you were to call target with the lambda closure type used to add the callback, this wouldn't work for two reasons: first, lambda closure types are unique (5.1.2p3) so the += and -= lambdas have different types even if they are syntactically identical; second, the closure type for a lambda-expression is not defined to have an operator== (5.1.2p3-6, 19-20), so your code would not even compile.
Switching from lambdas to std::bind wouldn't help, as bind types are also not defined to have operator==.
Instead, consider using an id to register/unregister callbacks. You could also use your own functor which defines operator==, but that would be a lot of work.

C++11 observer pattern (signals, slots, events, change broadcaster/listener, or whatever you want to call it)

With the changes made in C++11 (such as the inclusion of std::bind), is there a recommended way to implement a simple single-threaded observer pattern without dependence on anything external to the core language or standard library (like boost::signal)?
EDIT
If someone could post some code showing how dependence on boost::signal could be reduced using new language features, that would still be very useful.
I think that bind makes it easier to create slots (cfr. the 'preferred' syntax vs. the 'portable' syntax - that's all going away). The observer management, however, is not becoming less complex.
But as #R. Martinho Fernandes mentions: an std::vector<std::function< r(a1) > > is now easily created without the hassle for an (artificial) 'pure virtual' interface class.
Upon request: an idea on connection management - probably full of bugs, but you'll get the idea:
// note that the Func parameter is something
// like std::function< void(int,int) > or whatever, greatly simplified
// by the C++11 standard
template<typename Func>
struct signal {
typedef int Key; //
Key nextKey;
std::map<Key,Func> connections;
// note that connection management is the same in C++03 or C++11
// (until a better idea arises)
template<typename FuncLike>
Key connect( FuncLike f ) {
Key k=nextKey++;
connections[k]=f;
return k;
}
void disconnect(Key k){
connections.erase(k);
}
// note: variadic template syntax to be reviewed
// (not the main focus of this post)
template<typename Args...>
typename Func::return_value call(Args... args){
// supposing no subcription changes within call:
for(auto &connection: connections){
(*connection.second)(std::forward(...args));
}
}
};
Usage:
signal<function<void(int,int)>> xychanged;
void dump(int x, int y) { cout << x << ", " << y << endl; }
struct XY { int x, y; } xy;
auto dumpkey=xychanged.connect(dump);
auto lambdakey=xychanged.connect([&xy](int x, int y){ xy.x=x; xy.y=y; });
xychanged.call(1,2);
Since you're asking for code, my blog entry Performance of a C++11 Signal System contains a single-file implementation of a fully functional signal system based on C++11 features without further dependencies (albeit single-threaded, which was a performance requirement).
Here is a brief usage example:
Signal<void (std::string, int)> sig2;
sig2() += [] (std::string msg, int d) { /* handler logic */ };
sig2.emit ("string arg", 17);
More examples can be found in this unit test.
I wrote my own light weight Signal/Slot classes which return connection handles. The existing answer's key system is pretty fragile in the face of exceptions. You have to be exceptionally careful about deleting things with an explicit call. I much prefer using RAII for open/close pairs.
One notable lack of support in my library is the ability to get a return value from your calls. I believe boost::signal has methods of calculating the aggregate return values. In practice usually you don't need this and I just find it cluttering, but I may come up with such a return method for fun as an exercise in the future.
One cool thing about my classes is the Slot and SlotRegister classes. SlotRegister provides a public interface which you can safely link to a private Slot. This protects against external objects calling your observer methods. It's simple, but nice encapsulation.
I do not believe my code is thread safe, however.
//"MIT License + do not delete this comment" - M2tM : http://michaelhamilton.com
#ifndef __MV_SIGNAL_H__
#define __MV_SIGNAL_H__
#include <memory>
#include <utility>
#include <functional>
#include <vector>
#include <set>
#include "Utility/scopeGuard.hpp"
namespace MV {
template <typename T>
class Signal {
public:
typedef std::function<T> FunctionType;
typedef std::shared_ptr<Signal<T>> SharedType;
static std::shared_ptr< Signal<T> > make(std::function<T> a_callback){
return std::shared_ptr< Signal<T> >(new Signal<T>(a_callback, ++uniqueId));
}
template <class ...Arg>
void notify(Arg... a_parameters){
if(!isBlocked){
callback(std::forward<Arg>(a_parameters)...);
}
}
template <class ...Arg>
void operator()(Arg... a_parameters){
if(!isBlocked){
callback(std::forward<Arg>(a_parameters)...);
}
}
void block(){
isBlocked = true;
}
void unblock(){
isBlocked = false;
}
bool blocked() const{
return isBlocked;
}
//For sorting and comparison (removal/avoiding duplicates)
bool operator<(const Signal<T>& a_rhs){
return id < a_rhs.id;
}
bool operator>(const Signal<T>& a_rhs){
return id > a_rhs.id;
}
bool operator==(const Signal<T>& a_rhs){
return id == a_rhs.id;
}
bool operator!=(const Signal<T>& a_rhs){
return id != a_rhs.id;
}
private:
Signal(std::function<T> a_callback, long long a_id):
id(a_id),
callback(a_callback),
isBlocked(false){
}
bool isBlocked;
std::function< T > callback;
long long id;
static long long uniqueId;
};
template <typename T>
long long Signal<T>::uniqueId = 0;
template <typename T>
class Slot {
public:
typedef std::function<T> FunctionType;
typedef Signal<T> SignalType;
typedef std::shared_ptr<Signal<T>> SharedSignalType;
//No protection against duplicates.
std::shared_ptr<Signal<T>> connect(std::function<T> a_callback){
if(observerLimit == std::numeric_limits<size_t>::max() || cullDeadObservers() < observerLimit){
auto signal = Signal<T>::make(a_callback);
observers.insert(signal);
return signal;
} else{
return nullptr;
}
}
//Duplicate Signals will not be added. If std::function ever becomes comparable this can all be much safer.
bool connect(std::shared_ptr<Signal<T>> a_value){
if(observerLimit == std::numeric_limits<size_t>::max() || cullDeadObservers() < observerLimit){
observers.insert(a_value);
return true;
}else{
return false;
}
}
void disconnect(std::shared_ptr<Signal<T>> a_value){
if(!inCall){
observers.erase(a_value);
} else{
disconnectQueue.push_back(a_value);
}
}
template <typename ...Arg>
void operator()(Arg... a_parameters){
inCall = true;
SCOPE_EXIT{
inCall = false;
for(auto& i : disconnectQueue){
observers.erase(i);
}
disconnectQueue.clear();
};
for (auto i = observers.begin(); i != observers.end();) {
if (i->expired()) {
observers.erase(i++);
} else {
auto next = i;
++next;
i->lock()->notify(std::forward<Arg>(a_parameters)...);
i = next;
}
}
}
void setObserverLimit(size_t a_newLimit){
observerLimit = a_newLimit;
}
void clearObserverLimit(){
observerLimit = std::numeric_limits<size_t>::max();
}
int getObserverLimit(){
return observerLimit;
}
size_t cullDeadObservers(){
for(auto i = observers.begin(); i != observers.end();) {
if(i->expired()) {
observers.erase(i++);
}
}
return observers.size();
}
private:
std::set< std::weak_ptr< Signal<T> >, std::owner_less<std::weak_ptr<Signal<T>>> > observers;
size_t observerLimit = std::numeric_limits<size_t>::max();
bool inCall = false;
std::vector< std::shared_ptr<Signal<T>> > disconnectQueue;
};
//Can be used as a public SlotRegister member for connecting slots to a private Slot member.
//In this way you won't have to write forwarding connect/disconnect boilerplate for your classes.
template <typename T>
class SlotRegister {
public:
typedef std::function<T> FunctionType;
typedef Signal<T> SignalType;
typedef std::shared_ptr<Signal<T>> SharedSignalType;
SlotRegister(Slot<T> &a_slot) :
slot(a_slot){
}
//no protection against duplicates
std::shared_ptr<Signal<T>> connect(std::function<T> a_callback){
return slot.connect(a_callback);
}
//duplicate shared_ptr's will not be added
bool connect(std::shared_ptr<Signal<T>> a_value){
return slot.connect(a_value);
}
void disconnect(std::shared_ptr<Signal<T>> a_value){
slot.disconnect(a_value);
}
private:
Slot<T> &slot;
};
}
#endif
Supplimental scopeGuard.hpp:
#ifndef _MV_SCOPEGUARD_H_
#define _MV_SCOPEGUARD_H_
//Lifted from Alexandrescu's ScopeGuard11 talk.
namespace MV {
template <typename Fun>
class ScopeGuard {
Fun f_;
bool active_;
public:
ScopeGuard(Fun f)
: f_(std::move(f))
, active_(true) {
}
~ScopeGuard() { if(active_) f_(); }
void dismiss() { active_ = false; }
ScopeGuard() = delete;
ScopeGuard(const ScopeGuard&) = delete;
ScopeGuard& operator=(const ScopeGuard&) = delete;
ScopeGuard(ScopeGuard&& rhs)
: f_(std::move(rhs.f_))
, active_(rhs.active_) {
rhs.dismiss();
}
};
template<typename Fun>
ScopeGuard<Fun> scopeGuard(Fun f){
return ScopeGuard<Fun>(std::move(f));
}
namespace ScopeMacroSupport {
enum class ScopeGuardOnExit {};
template <typename Fun>
MV::ScopeGuard<Fun> operator+(ScopeGuardOnExit, Fun&& fn) {
return MV::ScopeGuard<Fun>(std::forward<Fun>(fn));
}
}
#define SCOPE_EXIT \
auto ANONYMOUS_VARIABLE(SCOPE_EXIT_STATE) \
= MV::ScopeMacroSupport::ScopeGuardOnExit() + [&]()
#define CONCATENATE_IMPL(s1, s2) s1##s2
#define CONCATENATE(s1, s2) CONCATENATE_IMPL(s1, s2)
#ifdef __COUNTER__
#define ANONYMOUS_VARIABLE(str) \
CONCATENATE(str, __COUNTER__)
#else
#define ANONYMOUS_VARIABLE(str) \
CONCATENATE(str, __LINE__)
#endif
}
#endif
An example application making use of my library:
#include <iostream>
#include <string>
#include "signal.hpp"
class Observed {
private:
//Note: This is private to ensure not just anyone can spawn a signal
MV::Slot<void (int)> onChangeSlot;
public:
typedef MV::Slot<void (int)>::SharedSignalType ChangeEventSignal;
//SlotRegister is public, users can hook up signals to onChange with this value.
MV::SlotRegister<void (int)> onChange;
Observed():
onChange(onChangeSlot){ //Here is where the binding occurs
}
void change(int newValue){
onChangeSlot(newValue);
}
};
class Observer{
public:
Observer(std::string a_name, Observed &a_observed){
connection = a_observed.onChange.connect([=](int value){
std::cout << a_name << " caught changed value: " << value << std::endl;
});
}
private:
Observed::ChangeEventSignal connection;
};
int main(){
Observed observed;
Observer observer1("o[1]", observed);
{
Observer observer2("o[2]", observed);
observed.change(1);
}
observed.change(2);
}
Output of the above would be:
o[1] caught changed value: 1
o[2] caught changed value: 1
o[1] caught changed value: 2
As you can see, the slot disconnects dead signals automatically.
Here's what I came up with.
This assumes no need to aggregate results from the listeners of a broadcast signal.
Also, the "slot" or Signal::Listener is the owner of the callback.
This ought to live with the object that your (I'm guessing...) lambda is probably capturing so that when that object goes out of scope, so does the callback, which prevents it from being called anymore.
You could use methods described in other answers as well to store the Listener owner objects in a way you can lookup.
template <typename... FuncArgs>
class Signal
{
using fp = std::function<void(FuncArgs...)>;
std::forward_list<std::weak_ptr<fp> > registeredListeners;
public:
using Listener = std::shared_ptr<fp>;
Listener add(const std::function<void(FuncArgs...)> &cb) {
// passing by address, until copy is made in the Listener as owner.
Listener result(std::make_shared<fp>(cb));
registeredListeners.push_front(result);
return result;
}
void raise(FuncArgs... args) {
registeredListeners.remove_if([&args...](std::weak_ptr<fp> e) -> bool {
if (auto f = e.lock()) {
(*f)(args...);
return false;
}
return true;
});
}
};
usage
Signal<int> bloopChanged;
// ...
Signal<int>::Listener bloopResponse = bloopChanged.add([](int i) { ... });
// or
decltype(bloopChanged)::Listener bloopResponse = ...
// let bloopResponse go out of scope.
// or re-assign it
// or reset the shared_ptr to disconnect it
bloopResponse.reset();
I have made a gist for this too, with a more in-depth example:
https://gist.github.com/johnb003/dbc4a69af8ea8f4771666ce2e383047d
I have had a go at this myself also. My efforts can be found at this gist, which will continue to evolve . . .
https://gist.github.com/4172757
I use a different style, more similar to the change notifications in JUCE than BOOST signals. Connection management is done using some lambda syntax that does some capture by copy. It is working well so far.

Binding to a weak_ptr

Is there a way to std::bind to a std::weak_ptr? I'd like to store a "weak function" callback that automatically "disconnects" when the callee is destroyed.
I know how to create a std::function using a shared_ptr:
std::function<void()> MyClass::GetCallback()
{
return std::function<void()>(std::bind(&MyClass::CallbackFunc, shared_from_this()));
}
However the returned std::function keeps my object alive forever. So I'd like to bind it to a weak_ptr:
std::function<void()> MyClass::GetCallback()
{
std::weak_ptr<MyClass> thisWeakPtr(shared_from_this());
return std::function<void()>(std::bind(&MyClass::CallbackFunc, thisWeakPtr));
}
But that doesn't compile. (std::bind will accept no weak_ptr!) Is there any way to bind to a weak_ptr?
I've found discussions about this (see below), but there seems to be no standard implementation. What is the best solution for storing a "weak function", in particular if Boost is not available?
Discussions / research (all of these use Boost and are not standardized):
weak_function
weak_ptr binding
"weak" binding (and a fix for it)
weak_fn
Another weak_fn
std::weak_ptr<MyClass> thisWeakPtr(shared_from_this());
return std::function<void()>(std::bind(&MyClass::CallbackFunc, thisWeakPtr));
You should never do this. Ever.
MyClass::CallbackFunc is a non-static member function of the class MyClass. Being a non-static member function, it must be called with a valid instance of MyClass.
The entire point of weak_ptr is that it isn't necessarily valid. You can detect its validity by transforming it into a shared_ptr and then testing if the pointer is NULL. Since weak_ptr is not guaranteed to be valid at all times, you cannot call a non-static member function with one.
What you're doing is no more valid than:
std::bind(&MyClass::CallbackFunc, nullptr)
It may compile, but it will eventually crash when you try to call it.
Your best bet is to use actual logic, to not call the callback function if the weak_ptr is not valid. bind is not designed to do logic; it just does exactly what you tell it to: call the function. So you need to use a proper lambda:
std::weak_ptr<MyClass> thisWeakPtr(shared_from_this());
return std::function<void()>([thisWeakPtr]()
{
auto myPtr = thisWeakPtr.lock();
if(myPtr)
myPtr->CallbackFunc()
});
I was able to create weak_pointers of std::function and tested it with clang-3.2 (you didn't give any compiler restrictions).
Here's a sample app that creates and tests what I believe you are asking for:
#include <functional>
#include <memory>
#include <iostream>
typedef std::function<void(void)> Func;
typedef std::shared_ptr<Func> SharedFunc;
typedef std::weak_ptr<Func> WeakFunc;
void Execute( Func f ) {
f();
}
void Execute( SharedFunc sf ) {
(*sf)();
}
void Execute( WeakFunc wf ) {
if ( auto f = wf.lock() )
(*f)();
else
std::cout << "Your backing pointer went away, sorry.\n";
}
int main(int, char**) {
auto f1 = [](){ std::cout << "Func here.\n"; };
Execute( f1 );
auto f2 = [](){ std::cout << "SharedFunc here.\n"; };
SharedFunc sf2( new Func(f2) );
Execute( sf2 );
auto f3 = [](){ std::cout << "WeakFunc here.\n"; };
SharedFunc sf3( new Func(f3) );
WeakFunc wf3( sf3 );
Execute( wf3 );
// Scoped test to make sure that the weak_ptr is really working.
WeakFunc wf4;
{
auto f4 = [](){ std::cout << "You should never see this.\n"; };
SharedFunc sf4( new Func(f4) );
wf4 = sf4;
}
Execute( wf4 );
return 0;
}
The output was:
~/projects/stack_overflow> clang++-mp-3.2 --std=c++11 --stdlib=libc++ weak_fun.cpp -o wf && ./wf
Func here.
SharedFunc here.
WeakFunc here.
Your backing pointer went away, sorry.
#include <iostream>
#include <string>
#include <memory>
#include <functional>
using namespace std;
template < typename T > class LockingPtr {
std :: weak_ptr < T > w;
public:
typedef shared_ptr < T > result_type;
LockingPtr ( const std :: shared_ptr < T > & p ) : w ( p ) { }
std :: shared_ptr < T > lock ( ) const {
return std :: shared_ptr < T > ( w );
}
std :: shared_ptr < T > operator-> ( ) const {
return lock ( );
}
template < typename ... Args > std :: shared_ptr < T > operator( ) ( Args ... ) const {
return lock ( );
}
};
template < typename T > LockingPtr < T > make_locking ( const shared_ptr < T > & p ) {
return p;
}
namespace std {
template < typename T > struct is_bind_expression < LockingPtr < T > > :
public true_type { };
}
int main() {
auto p = make_shared < string > ( "abc" );
auto f = bind ( & string :: c_str, make_locking ( p ) );
cout << f ( ) << '\n';
p.reset ( );
try {
cout << f ( ) << '\n';
} catch ( const exception & e ) {
cout << e.what ( ) << '\n';
}
// your code goes here
return 0;
}
output:
abc
bad_weak_ptr
I know this is an old question, but I have the same requirement and I'm sure I'm not alone.
The solution in the end for me was to return a function object that returns a boost::optional<> depending on whether the function was called or not.
code here:
#include <boost/optional.hpp>
#include <memory>
namespace value { namespace stdext {
using boost::optional;
using boost::none;
struct called_flag {};
namespace detail
{
template<class Target, class F>
struct weak_binder
{
using target_type = Target;
using weak_ptr_type = std::weak_ptr<Target>;
weak_binder(weak_ptr_type weak_ptr, F f)
: _weak_ptr(std::move(weak_ptr))
, _f(std::move(f))
{}
template<class...Args,
class Result = std::result_of_t<F(Args...)>,
std::enable_if_t<not std::is_void<Result>::value>* = nullptr>
auto operator()(Args&&...args) const -> optional<Result>
{
auto locked_ptr = _weak_ptr.lock();
if (locked_ptr)
{
return _f(std::forward<Args>(args)...);
}
else
{
return none;
}
}
template<class...Args,
class Result = std::result_of_t<F(Args...)>,
std::enable_if_t<std::is_void<Result>::value>* = nullptr>
auto operator()(Args&&...args) const -> optional<called_flag>
{
auto locked_ptr = _weak_ptr.lock();
if (locked_ptr)
{
_f(std::forward<Args>(args)...);
return called_flag {};
}
else
{
return none;
}
}
weak_ptr_type _weak_ptr;
F _f;
};
}
template<class Ret, class Target, class...FuncArgs, class Pointee, class...Args>
auto bind_weak(Ret (Target::*mfp)(FuncArgs...), const std::shared_ptr<Pointee>& ptr, Args&&...args)
{
using binder_type = decltype(std::bind(mfp, ptr.get(), std::forward<Args>(args)...));
return detail::weak_binder<Target, binder_type>
{
std::weak_ptr<Target>(ptr),
std::bind(mfp, ptr.get(), std::forward<Args>(args)...)
};
}
}}
called (for example) like so:
TEST(bindWeakTest, testBasics)
{
struct Y
{
void bar() {};
};
struct X : std::enable_shared_from_this<X>
{
int increment(int by) {
count += by;
return count;
}
void foo() {
}
Y y;
int count = 0;
};
auto px = std::make_shared<X>();
auto wf = value::stdext::bind_weak(&X::increment, px, std::placeholders::_1);
auto weak_call_bar = value::stdext::bind_weak(&Y::bar, std::shared_ptr<Y>(px, &px->y));
auto ret1 = wf(4);
EXPECT_TRUE(bool(ret1));
EXPECT_EQ(4, ret1.get());
auto wfoo1 = value::stdext::bind_weak(&X::foo, px);
auto retfoo1 = wfoo1();
EXPECT_TRUE(bool(retfoo1));
auto retbar1 = weak_call_bar();
EXPECT_TRUE(bool(retbar1));
px.reset();
auto ret2 = wf(4);
EXPECT_FALSE(bool(ret2));
auto retfoo2 = wfoo1();
EXPECT_FALSE(bool(retfoo2));
auto retbar2 = weak_call_bar();
EXPECT_FALSE(bool(retbar2));
}
source code and tests available here:
https://github.com/madmongo1/valuelib
Not sure why that definition is not in boost. There must be a good reason (how to deal with lock fail? Is throwing from there acceptable? Thread safety?) Anyway, that will validate your callee.
namespace boost {
template<class T> T * get_pointer(boost::weak_ptr<T> const& p)
{
boost::shared_ptr< T > _strong = p.lock();
if( _strong )
return _strong.get();
else
throw 1;
}
}
int main(int arg, char *argv[])
{
boost::weak_ptr< MyType > weak_bad;
{
boost::shared_ptr< MyType > strong(new MyType);
boost::weak_ptr< MyType > weak(strong);
boost::function< void(int) > _func1 = boost::bind(&MyType::setX, weak, _1);
_func1(10);
weak_bad = strong;
}
try {
boost::function< void(int) > _func1 = boost::bind(&MyType::setX, weak_bad, _1);
_func1(10);
}
catch(...)
{
std::cout << "oops!";
}
return 0;
};
Another solution:
You could wrap the std::function. The class producing the callback would hold a shared_ptr< wrapper_type > and provide a weak_ptr< wrapper_type >. The producing object would be the one with the ownership, if it goes out of scope, callers won't be able to promote their weak reference. Your wrapper type could forward call arguments to the std::function or simply expose it via its interface. Just make sure that on copy you properly handle the shared_ptr on the wrapper (don't share).
template< typename _Ty >
struct wrapper
{
wrapper(_Ty wrappe)
: _wrappe(wrappe)
{ }
_Ty _wrappe;
};
...
boost::shared_ptr< wrapper < std::func< ... > > _func(new wrapper < std::func< ... > );
...
boost::weak_ptr< wrapper < std::func< ... > getCallBack() {
return _func;
}
How about this? it works only for actions std::function<void()> but perhaps it can be generalized for arbitrarily parameterized functions.
#include <memory>
#include <functional>
template<typename T>
void
perform_action_or_ignore_when_null(
std::weak_ptr<T> weak,
std::function< void( std::shared_ptr<T> ) > func
)
{
if(auto ptr = weak.lock())
func(ptr);
}
template<typename T>
std::function<void()>
ignore_when_null(
std::weak_ptr<T> weak,
std::function< void( std::shared_ptr<T> ) > func
)
{
return std::bind(perform_action_or_ignore_when_null<T>, weak, func);
}
here's an example usage:
struct Foo {
Foo() {}
void bar() {
std::cout << "hello world!" << std::endl;
}
};
void main()
{
std::weak_ptr<Foo> weakfoo;
std::function<void(std::shared_ptr<Foo>)> foobar = std::bind(&Foo::bar, std::placeholders::_1);
{
auto foo = std::make_shared<Foo>();
weakfoo = foo;
auto f = ignore_when_null(weakfoo, foobar);
f(); // prints "hello world!";
}
auto g = ignore_when_null(weakfoo, foobar);
g(); // does nothing
}
You can bind weak_ptr to the function as one of parameters,
and check it when the function is called.
For example:
std::function<void()> MyClass::GetCallback()
{
std::weak_ptr<MyClass> thisWeakPtr(shared_from_this());
return std::function<void()>(std::bind(&MyClass::CallbackFunc, this,
thisWeakPtr));
}
void MyClass::CallbackFunc(const std::weak_ptr<MyClass>& thisWeakPtr)
{
if (!thisWeakPtr.lock()) {
return;
}
// Do your callback job.
// ...
}