MPD: util/BindMethod.hxx Source File

MPD 0.20.15

BindMethod.hxx
Go to the documentation of this file.
1 /*
2 * Copyright (C) 2016 Max Kellermann <max.kellermann@gmail.com>
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * - Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 *
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the
14 * distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
19 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
20 * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
25 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
27 * OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30 #ifndef BIND_METHOD_HXX
31 #define BIND_METHOD_HXX
32
33 #include <type_traits>
34 #include <utility>
35
43 template<typename S=void()>
44 class BoundMethod;
45
46 template<typename R, typename... Args>
47 class BoundMethod<R(Args...)> {
48 typedef R (*function_pointer)(void *instance, Args... args);
49
50 void *instance_;
51 function_pointer function;
52
53 public:
57 BoundMethod() = default;
58
59 constexpr
60 BoundMethod(void *_instance, function_pointer _function)
61 :instance_(_instance), function(_function) {}
62
67 BoundMethod(std::nullptr_t):function(nullptr) {}
68
72 operator bool() const {
73 return function != nullptr;
74 }
75
76 R operator()(Args... args) const {
77 return function(instance_, std::forward<Args>(args)...);
78 }
79 };
80
81 namespace BindMethodDetail {
82
91 template<typename T, typename S>
92 struct MethodWithSignature;
93
94 template<typename T, typename R, typename... Args>
95 struct MethodWithSignature<T, R(Args...)> {
96 typedef R (T::*method_pointer)(Args...);
97 };
98
104 template<typename M>
105 struct MethodSignatureHelper;
106
107 template<typename R, typename T, typename... Args>
108 struct MethodSignatureHelper<R (T::*)(Args...)> {
112 typedef T class_type;
113
118 typedef R plain_signature(Args...);
119 };
120
125 template<typename S>
126 struct MethodWrapperWithSignature;
127
128 template<typename R, typename... Args>
129 struct MethodWrapperWithSignature<R(Args...)> {
130 typedef R (*function_pointer)(void *instance, Args...);
131 };
132
143 template<typename T, typename M, M method, typename R, typename... Args>
144 struct BindMethodWrapperGenerator2 {
145 static R Invoke(void *_instance, Args... args) {
146 auto &t = *(T *)_instance;
147 return (t.*method)(std::forward<Args>(args)...);
148 }
149 };
150
159 template<typename T, typename M, M method, typename S>
160 struct BindMethodWrapperGenerator;
161
162 template<typename T, typename M, M method, typename R, typename... Args>
163 struct BindMethodWrapperGenerator<T, M, method, R(Args...)>
164 : BindMethodWrapperGenerator2<T, M, method, R, Args...> {
165 };
166
167 template<typename T, typename S,
168 typename MethodWithSignature<T, S>::method_pointer method>
169 typename MethodWrapperWithSignature<S>::function_pointer
170 MakeBindMethodWrapper()
171 {
172 return BindMethodWrapperGenerator<T, typename MethodWithSignature<T, S>::method_pointer, method, S>::Invoke;
173 }
174
175 } /* namespace BindMethodDetail */
176
185 template<typename T, typename S,
186 typename BindMethodDetail::MethodWithSignature<T, S>::method_pointer method>
187 constexpr BoundMethod<S>
188 BindMethod(T &_instance)
189 {
190 return BoundMethod<S>(&_instance,
191 BindMethodDetail::MakeBindMethodWrapper<T, S, method>());
192 }
193
198 #define BIND_METHOD(instance, method) \
199 BindMethod<typename BindMethodDetail::MethodSignatureHelper<decltype(method)>::class_type, \
200 typename BindMethodDetail::MethodSignatureHelper<decltype(method)>::plain_signature, \
201 method>(instance)
202
207 #define BIND_THIS_METHOD(method) BIND_METHOD(*this, &std::remove_reference<decltype(*this)>::type::method)
208
209 #endif
BindMethodDetail::BindMethodWrapperGenerator2
Generate a wrapper function.
Definition: BindMethod.hxx:144
BindMethodDetail
Definition: BindMethod.hxx:81
BoundMethod< R(Args...)>::BoundMethod
BoundMethod(std::nullptr_t)
Construct an "undefined" object.
Definition: BindMethod.hxx:67
BindMethodDetail::BindMethodWrapperGenerator
Generate a wrapper function.
Definition: BindMethod.hxx:160
BoundMethod< R(Args...)>::operator()
R operator()(Args... args) const
Definition: BindMethod.hxx:76
BoundMethod
This object stores a function pointer wrapping a method, and a reference to an instance of the method...
Definition: BindMethod.hxx:44
BindMethodDetail::MethodWithSignature
Helper class which converts a signature type to a method pointer type.
Definition: BindMethod.hxx:92
instance
Instance * instance
BindMethodDetail::MethodWrapperWithSignature
Helper class which converts a plain function signature type to a wrapper function pointer type...
Definition: BindMethod.hxx:126
BindMethodDetail::MethodSignatureHelper
Helper class which introspects a method pointer type.
Definition: BindMethod.hxx:105
BindMethodDetail::BindMethodWrapperGenerator2::Invoke
static R Invoke(void *_instance, Args... args)
Definition: BindMethod.hxx:145
BindMethodDetail::MethodSignatureHelper< R(T::*)(Args...)>::class_type
T class_type
The class which contains the given method (signature).
Definition: BindMethod.hxx:112
BindMethodDetail::MethodSignatureHelper< R(T::*)(Args...)>::plain_signature
R plain_signature(Args...)
A function type which describes the "plain" function signature.
Definition: BindMethod.hxx:118
BindMethod
constexpr BoundMethod< S > BindMethod(T &_instance)
Construct a BoundMethod instance.
Definition: BindMethod.hxx:188
BoundMethod< R(Args...)>::BoundMethod
constexpr BoundMethod(void *_instance, function_pointer _function)
Definition: BindMethod.hxx:60
BindMethodDetail::MakeBindMethodWrapper
MethodWrapperWithSignature< S >::function_pointer MakeBindMethodWrapper()
Definition: BindMethod.hxx:170