Skip to content

Instantly share code, notes, and snippets.

@fcamel
Last active November 8, 2022 06:50
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fcamel/36ccc5713bc6d3ce96fdc7ad02feaa8f to your computer and use it in GitHub Desktop.
Save fcamel/36ccc5713bc6d3ce96fdc7ad02feaa8f to your computer and use it in GitHub Desktop.
// std::bind() cannot bind std::weak_ptr.
// This file provides BindWeakPtr() which can bind a method with a std::weak_ptr.
// If the object inside weak_ptr is deleted, the function will become a NOP.
#include <iostream>
#include <functional>
#include <memory>
template <typename T>
class WeakFunction
{
public:
typedef std::function<void(std::shared_ptr<T>)> Function;
WeakFunction(std::weak_ptr<T> p, const Function& function)
: m_p(p)
, m_function(function)
{
}
void operator()()
{
auto p = m_p.lock();
if (p) {
m_function(p);
}
}
private:
std::weak_ptr<T> m_p;
Function m_function;
};
template <typename T>
struct IsWeakPtr { static const bool value = false; };
template <typename T>
struct IsWeakPtr<std::weak_ptr<T> > { static const bool value = true; };
template <typename Method, typename Class, typename... Args>
std::function<void()> BindWeakPtr(Method m, Class o, Args&&... args)
{
static_assert(IsWeakPtr<Class>::value, "Not a weak_ptr");
auto f = std::bind(m, std::placeholders::_1, std::forward<Args>(args)...);
WeakFunction<typename Class::element_type> wf(o, f);
return std::bind(wf);
}
//------------------------------------------------------------------------------
class A
{
public:
A(int result) : m_result(result) {}
void Multiple(int a) { m_result *= a; }
int GetResult() { return m_result; }
private:
int m_result;
};
int main(void)
{
std::shared_ptr<A> a(new A(1));
std::weak_ptr<A> w(a);
std::function<void()> f = std::bind(&A::Multiple, a, 5);
//std::function<void()> f2 = std::bind(&A::Multiple, w, 6); // Compilation error.
std::function<void()> f3 = BindWeakPtr(&A::Multiple, w, 7); // OK.
f(); // a->Mutltiple(5);
f3(); // auto p = w.lock(); if (p) p->Multiple(7);
std::cout << a->GetResult() << std::endl;
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment