OGLplus  (0.59.0) a C++ wrapper for rendering APIs

callable_ref.hpp
Go to the documentation of this file.
1 
9 #ifndef EAGINE_CALLABLE_REF_HPP
10 #define EAGINE_CALLABLE_REF_HPP
11 
12 #include "assert.hpp"
13 #include "mem_func_const.hpp"
14 #include "selector.hpp"
15 #include "type_traits.hpp"
16 #include <utility>
17 
18 namespace eagine {
19 
23 template <typename FuncSig, bool NoExcept>
25 
34 template <typename RV, typename... P, bool NE>
35 class basic_callable_ref<RV(P...) noexcept(NE), NE> {
36 public:
38  using argument_tuple_type =
39  std::tuple<std::remove_cv_t<std::remove_reference_t<P>>...>;
40 
42  static auto argument_tuple() noexcept -> argument_tuple_type {
43  return {};
44  }
45 
48  constexpr basic_callable_ref() noexcept = default;
49 
51  constexpr basic_callable_ref(basic_callable_ref&& temp) noexcept
52  : _data{std::exchange(temp._data, nullptr)}
53  , _func{std::exchange(temp._func, nullptr)} {}
54 
56  constexpr basic_callable_ref(const basic_callable_ref&) noexcept = default;
57 
59  constexpr auto operator=(basic_callable_ref&& temp) noexcept
60  -> basic_callable_ref& {
61  std::swap(temp._data, _data);
62  std::swap(temp._func, _func);
63  return *this;
64  }
65 
67  constexpr auto operator=(const basic_callable_ref&) noexcept
68  -> basic_callable_ref& = default;
69 
70  ~basic_callable_ref() noexcept = default;
71 
73  basic_callable_ref(RV (*func)(P...) noexcept(NE)) noexcept
74  : _func{reinterpret_cast<_func_t>(func)} {}
75 
77  template <typename T>
78  basic_callable_ref(T* data, RV (*func)(T*, P...) noexcept(NE)) noexcept
79  : _data{static_cast<void*>(data)}
80  , _func{reinterpret_cast<_func_t>(func)} {
81  EAGINE_ASSERT(_data != nullptr);
82  }
83 
85  template <typename T>
86  basic_callable_ref(T& data, RV (*func)(T*, P...) noexcept(NE)) noexcept
87  : _data(static_cast<void*>(&data))
88  , _func(reinterpret_cast<_func_t>(func)) {}
89 
91  template <
92  typename C,
93  typename = std::enable_if_t<!std::is_same_v<C, basic_callable_ref>>>
95  : _data(static_cast<void*>(&obj))
96  , _func(reinterpret_cast<_func_t>(&_cls_fn_call_op<C>)) {}
97 
99  template <
100  typename C,
101  typename = std::enable_if_t<!std::is_same_v<C, basic_callable_ref>>>
102  basic_callable_ref(construct_from_t, const C& obj) noexcept
103  : _data(static_cast<void*>(const_cast<C*>(&obj)))
104  , _func(reinterpret_cast<_func_t>(&_cls_fn_call_op_c<C>)) {}
105 
107  template <typename C, RV (C::*Ptr)(P...) noexcept(NE)>
109  C* obj,
110  member_function_constant<RV (C::*)(P...) noexcept(NE), Ptr> mfc) noexcept
111  : _data(static_cast<void*>(obj))
112  , _func(reinterpret_cast<_func_t>(mfc.make_free())) {
113  EAGINE_ASSERT(_data != nullptr);
114  EAGINE_ASSERT(_func != nullptr);
115  }
116 
118  template <typename C, RV (C::*Ptr)(P...) const noexcept(NE)>
120  const C* obj,
121  member_function_constant<RV (C::*)(P...) const noexcept(NE), Ptr>
122  mfc) noexcept
123  : _data(static_cast<void*>(const_cast<C*>(obj)))
124  , _func(reinterpret_cast<_func_t>(mfc.make_free())) {
125  EAGINE_ASSERT(_data != nullptr);
126  EAGINE_ASSERT(_func != nullptr);
127  }
128 
130  constexpr auto is_valid() const noexcept {
131  return _func != nullptr;
132  }
133 
136  explicit constexpr operator bool() const noexcept {
137  return is_valid();
138  }
139 
142  template <typename... A>
143  auto operator()(A&&... a) const -> RV {
144  EAGINE_ASSERT(is_valid());
145  if(_data == nullptr) {
146  return (reinterpret_cast<_func_pt>(_func))(std::forward<A>(a)...);
147  } else {
148  return (reinterpret_cast<_func_vpt>(_func))(
149  _data, std::forward<A>(a)...);
150  }
151  }
152 
153 private:
154  void* _data{nullptr};
155  void (*_func)() noexcept(NE){nullptr};
156 
157  using _func_t = void (*)() noexcept(NE);
158  using _func_pt = RV (*)(P...) noexcept(NE);
159  using _func_vpt = RV (*)(void*, P...) noexcept(NE);
160 
161  template <typename C>
162  static auto _cls_fn_call_op(void* that, P... p) noexcept(NE) -> RV {
163  EAGINE_ASSERT(that);
164  C& obj = *(static_cast<C*>(that));
165 
166  // NOLINTNEXTLINE(hicpp-braces-around-statements,readability-braces-around-statements)
167  if constexpr(std::is_void_v<RV>) {
168  obj(std::forward<P>(p)...);
169  } else {
170  return obj(std::forward<P>(p)...);
171  }
172  }
173 
174  template <typename C>
175  static auto _cls_fn_call_op_c(void* that, P... p) noexcept(NE) -> RV {
176  EAGINE_ASSERT(that);
177  const C& obj = *(static_cast<const C*>(that));
178 
179  // NOLINTNEXTLINE(hicpp-braces-around-statements,readability-braces-around-statements)
180  if constexpr(std::is_void_v<RV>) {
181  obj(std::forward<P>(p)...);
182  } else {
183  return obj(std::forward<P>(p)...);
184  }
185  }
186 };
187 
190 template <typename Sig>
192 
193 } // namespace eagine
194 
195 #endif // EAGINE_CALLABLE_REF_HPP
Declaration of class template storing a reference to a callable object.
Definition: callable_ref.hpp:24
basic_callable_ref(C *obj, member_function_constant< RV(C::*)(P...) noexcept(NE), Ptr > mfc) noexcept
Construction a pointer to object and member function constant.
Definition: callable_ref.hpp:108
constexpr auto is_valid() const noexcept
Indicates if this object stores a valid callable reference.
Definition: callable_ref.hpp:130
Common code is placed in this namespace.
Definition: eagine.hpp:21
basic_callable_ref(const C *obj, member_function_constant< RV(C::*)(P...) const noexcept(NE), Ptr > mfc) noexcept
Construction a pointer to const object and member function constant.
Definition: callable_ref.hpp:119
std::tuple< std::remove_cv_t< std::remove_reference_t< P > >... > argument_tuple_type
Alias for the callable's argument type tuple.
Definition: callable_ref.hpp:39
basic_callable_ref(construct_from_t, C &obj) noexcept
Construction a reference to object with a call operator.
Definition: callable_ref.hpp:94
Template used to construct tag-types used mostly in tag-dispatching.
Definition: selector.hpp:21
constexpr auto operator=(basic_callable_ref &&temp) noexcept -> basic_callable_ref &
Move assignment operator.
Definition: callable_ref.hpp:59
basic_callable_ref(construct_from_t, const C &obj) noexcept
Construction a const reference to object with a call operator.
Definition: callable_ref.hpp:102
basic_callable_ref(T *data, RV(*func)(T *, P...) noexcept(NE)) noexcept
Construction from pointers to an object and a function.
Definition: callable_ref.hpp:78
static auto argument_tuple() noexcept -> argument_tuple_type
Creates a default-constructed instance of argument_type_tuple.
Definition: callable_ref.hpp:42
Declaration of compile-time member function pointer wrappers.
Definition: mem_func_const.hpp:19
basic_callable_ref(T &data, RV(*func)(T *, P...) noexcept(NE)) noexcept
Construction from a reference to an object and a pointer to function.
Definition: callable_ref.hpp:86
auto operator()(A &&... a) const -> RV
Call operator.
Definition: callable_ref.hpp:143

Copyright © 2015-2021 Matúš Chochlík.
<chochlik -at -gmail.com>
Documentation generated on Tue Apr 13 2021 by Doxygen (version 1.8.17).