File size: 2,798 Bytes
985c397
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#pragma once

#include <functional>
#include <memory>
#include <type_traits>

namespace fastsignals
{
namespace detail
{
template <class ReturnType, class ClassType, bool AddConst, class... Args>
struct weak_binder

{
	using ConstMethodType = ReturnType (ClassType::*)(Args... args) const;
	using NonConstMethodType = ReturnType (ClassType::*)(Args... args);
	using MethodType = std::conditional_t<AddConst, ConstMethodType, NonConstMethodType>;
	using WeakPtrType = std::weak_ptr<ClassType>;

	weak_binder(MethodType pMethod, WeakPtrType&& pObject)
		: m_pMethod(pMethod)
		, m_pObject(std::move(pObject))
	{
	}

	ReturnType operator()(Args... args) const
	{
		if (auto pThis = m_pObject.lock())
		{
			return (pThis.get()->*m_pMethod)(std::forward<Args>(args)...);
		}
		return ReturnType();
	}

	MethodType m_pMethod;
	WeakPtrType m_pObject;
};
} // namespace detail

/// Weak this binding of non-const methods.
template <typename ReturnType, typename ClassType, typename... Params, typename... Args>
decltype(auto) bind_weak(ReturnType (ClassType::*memberFn)(Params... args), std::shared_ptr<ClassType> const& pThis, Args... args)
{
	using weak_binder_alias = detail::weak_binder<ReturnType, ClassType, false, Params...>;

	weak_binder_alias invoker(memberFn, std::weak_ptr<ClassType>(pThis));
	return std::bind(invoker, args...);
}

/// Weak this binding of const methods.
template <typename ReturnType, typename ClassType, typename... Params, typename... Args>
decltype(auto) bind_weak(ReturnType (ClassType::*memberFn)(Params... args) const, std::shared_ptr<ClassType> const& pThis, Args... args)
{
	using weak_binder_alias = detail::weak_binder<ReturnType, ClassType, true, Params...>;

	weak_binder_alias invoker(memberFn, std::weak_ptr<ClassType>(pThis));
	return std::bind(invoker, args...);
}

/// Weak this binding of non-const methods.
template <typename ReturnType, typename ClassType, typename... Params, typename... Args>
decltype(auto) bind_weak(ReturnType (ClassType::*memberFn)(Params... args), std::weak_ptr<ClassType> pThis, Args... args)
{
	using weak_binder_alias = detail::weak_binder<ReturnType, ClassType, false, Params...>;

	weak_binder_alias invoker(memberFn, std::move(pThis));
	return std::bind(invoker, args...);
}

/// Weak this binding of const methods.
template <typename ReturnType, typename ClassType, typename... Params, typename... Args>
decltype(auto) bind_weak(ReturnType (ClassType::*memberFn)(Params... args) const, std::weak_ptr<ClassType> pThis, Args... args)
{
	using weak_binder_alias = detail::weak_binder<ReturnType, ClassType, true, Params...>;

	weak_binder_alias invoker(memberFn, std::move(pThis));
	return std::bind(invoker, args...);
}

} // namespace fastsignals