ThreadSchedule 2.2.0
Modern C++ thread management library
Loading...
Searching...
No Matches
callable.hpp
Go to the documentation of this file.
1#pragma once
2
7
8#include <functional>
9#include <memory>
10#include <type_traits>
11#include <utility>
12
13#if defined(__has_include)
14# if __has_include(<version>)
15# include <version>
16# endif
17#endif
18
20{
21namespace detail
22{
23
24template <typename T>
25using remove_cvref_t = std::remove_cv_t<std::remove_reference_t<T>>;
26
27#if defined(__cpp_lib_move_only_function) && __cpp_lib_move_only_function >= 202110L
28template <typename Signature>
29using move_callable = std::move_only_function<Signature>;
30#else
31template <typename Signature>
32using move_callable = std::function<Signature>;
33#endif
34
35#if defined(__cpp_lib_copyable_function) && __cpp_lib_copyable_function >= 202306L
36template <typename Signature>
37using copyable_callable = std::copyable_function<Signature>;
38#else
39template <typename Signature>
40using copyable_callable = std::function<Signature>;
41#endif
42
43#if defined(__cpp_lib_function_ref) && __cpp_lib_function_ref >= 202306L
44template <typename Signature>
45using function_ref = std::function_ref<Signature>;
46#else
47template <typename Signature>
49
50template <typename R, typename... Args>
51class function_ref<R(Args...)>
52{
53 public:
54 function_ref() = delete;
55
56 function_ref(R (*fn)(Args...)) noexcept : function_(fn)
57 {
58 callback_ = [](void*, R (*function)(Args...), Args... args) -> R {
59 if constexpr (std::is_void_v<R>)
60 {
61 function(std::forward<Args>(args)...);
62 return;
63 }
64 else
65 {
66 return function(std::forward<Args>(args)...);
67 }
68 };
69 }
70
71 template <typename F,
72 typename = std::enable_if_t<!std::is_same_v<remove_cvref_t<F>, function_ref> &&
73 std::is_invocable_r_v<R, F&, Args...>>>
74 function_ref(F&& fn) noexcept : object_(const_cast<void*>(static_cast<void const*>(std::addressof(fn))))
75 {
76 callback_ = [](void* object, R (*)(Args...), Args... args) -> R {
77 auto& callable = *static_cast<remove_cvref_t<F>*>(object);
78 if constexpr (std::is_void_v<R>)
79 {
80 callable(std::forward<Args>(args)...);
81 return;
82 }
83 else
84 {
85 return callable(std::forward<Args>(args)...);
86 }
87 };
88 }
89
90 auto operator()(Args... args) const -> R
91 {
92 if constexpr (std::is_void_v<R>)
93 {
94 callback_(object_, function_, std::forward<Args>(args)...);
95 return;
96 }
97 else
98 {
99 return callback_(object_, function_, std::forward<Args>(args)...);
100 }
101 }
102
103 private:
104 void* object_ = nullptr;
105 R (*function_)(Args...) = nullptr;
106 R (*callback_)(void*, R (*)(Args...), Args...);
107};
108#endif
109
110template <typename Signature, typename Callable>
112{
113 return move_callable<Signature>(std::forward<Callable>(callable));
114}
115
116template <typename Signature, typename Callable>
118{
119 return copyable_callable<Signature>(std::forward<Callable>(callable));
120}
121
122} // namespace detail
123} // namespace threadschedule
auto operator()(Args... args) const -> R
Definition callable.hpp:90
std::function< Signature > copyable_callable
Definition callable.hpp:40
auto make_move_callable(Callable &&callable) -> move_callable< Signature >
Definition callable.hpp:111
std::function< Signature > move_callable
Definition callable.hpp:32
std::remove_cv_t< std::remove_reference_t< T > > remove_cvref_t
Definition callable.hpp:25
auto make_copyable_callable(Callable &&callable) -> copyable_callable< Signature >
Definition callable.hpp:117