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()>
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>
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>
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>
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>
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>
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,
171 {
173 }
174 
175 } /* namespace BindMethodDetail */
176 
185 template<typename T, typename S,
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
BoundMethod(std::nullptr_t)
Construct an "undefined" object.
Definition: BindMethod.hxx:67
R operator()(Args... args) const
Definition: BindMethod.hxx:76
This object stores a function pointer wrapping a method, and a reference to an instance of the method...
Definition: BindMethod.hxx:44
Helper class which converts a signature type to a method pointer type.
Definition: BindMethod.hxx:92
Instance * instance
Helper class which converts a plain function signature type to a wrapper function pointer type...
Definition: BindMethod.hxx:126
Helper class which introspects a method pointer type.
Definition: BindMethod.hxx:105
static R Invoke(void *_instance, Args... args)
Definition: BindMethod.hxx:145
T class_type
The class which contains the given method (signature).
Definition: BindMethod.hxx:112
R plain_signature(Args...)
A function type which describes the "plain" function signature.
Definition: BindMethod.hxx:118
constexpr BoundMethod< S > BindMethod(T &_instance)
Construct a BoundMethod instance.
Definition: BindMethod.hxx:188
constexpr BoundMethod(void *_instance, function_pointer _function)
Definition: BindMethod.hxx:60
MethodWrapperWithSignature< S >::function_pointer MakeBindMethodWrapper()
Definition: BindMethod.hxx:170