-
Notifications
You must be signed in to change notification settings - Fork 9
/
Function.h
181 lines (157 loc) · 6.76 KB
/
Function.h
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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
/*
* Copyright(c) Sophist Solutions, Inc. 1990-2022. All rights reserved
*/
#ifndef _Stroika_Foundation_Execution_Function_h_
#define _Stroika_Foundation_Execution_Function_h_ 1
#include "../StroikaPreComp.h"
#if defined(__cpp_impl_three_way_comparison)
#include <compare>
#endif
#include <functional>
#include <memory>
#include "../Configuration/Common.h"
/**
* \file
*
* \version <a href="Code-Status.md#Beta">Beta</a>
*
* TODO
* @todo Instead of using shared_ptr<> - we could have an INT counter (except for special case of null where we use
* 0). That might be cheaper, and preserve the same semantics.
*
* @todo Better understand, and fix qFoundation_Execution_Function_OperatorForwardNeedsRefBug, and eliminate it
*
* @todo Consider if this should be copy-by-value (use SharedByValue instead of shared_ptr) so it more closely
* mimics copy behavior of std::function?
*/
/// NOT SURE WHAT's GOING ON. Seems like my bug, but I don't fully
/// understand
/// doesn't seem needed with msvc, but is with gcc/clang++
#ifndef qFoundation_Execution_Function_OperatorForwardNeedsRefBug
#define qFoundation_Execution_Function_OperatorForwardNeedsRefBug 1
#endif
namespace Stroika::Foundation::Characters {
class String;
}
namespace Stroika::Foundation::Execution {
/**
* IDEA is be SAME AS std::function<> but allow for operator<, a usable operator== etc...,
* which is an unfortunate omission from the c++ standard.
*
* This should be convertable to a normal std::function<>, and fairly if not totally interoprable.
*
* \note Alias
* This template could have been called Callback<> - as thats principally what its used for.
* Callbacks you need to be able to create, and then later remove (by value) - and this class
* lets you create an object (callback/Function) - which can then be added to a Mapping (or Set)
* and then later removed by value.
*
* \note This was implemented using a shared_ptr<function<...>> instead of a directly aggregated function object
* until Stroika v2.1d8.
*
* \note <a href="Design Overview.md#Comparisons">Comparisons</a>:
* o Standard Stroika Comparison support (operator<=>,operator==, etc);
*/
template <typename FUNCTION_SIGNATURE>
class Function {
public:
using STDFUNCTION = function<FUNCTION_SIGNATURE>;
public:
/**
*/
using result_type = typename STDFUNCTION::result_type;
public:
/**
* \note Implementation note:
* Reason for the not is_base_of_v<> restriction on CTOR/1(CTOR_FUNC_SIG&&) is to prevent compiler from
* instantiating that constructor template for argument subclasses of this Function type, and having those take precedence over the
* default X(const X&) CTOR.
*
* And also careful not to apply to non-functions.
*/
Function () = default;
Function (nullptr_t);
Function (const Function&) = default;
Function (Function&&) = default;
template <typename CTOR_FUNC_SIG, enable_if_t<is_convertible_v<CTOR_FUNC_SIG, function<FUNCTION_SIGNATURE>> and not is_base_of_v<Function<FUNCTION_SIGNATURE>, Configuration::remove_cvref_t<CTOR_FUNC_SIG>>>* = nullptr>
Function (CTOR_FUNC_SIG&& f);
public:
/**
*/
nonvirtual Function& operator= (Function&&) = default;
nonvirtual Function& operator= (const Function&) = default;
public:
/**
*/
nonvirtual operator STDFUNCTION () const;
public:
/**
*/
template <typename... Args>
nonvirtual result_type operator() (Args... args) const;
public:
struct ThreeWayComparer;
#if __cpp_impl_three_way_comparison >= 201907
public:
/**
*/
nonvirtual strong_ordering operator<=> (const Function& rhs) const;
public:
/**
*/
nonvirtual bool operator== (const Function& rhs) const;
#endif
public:
/**
* @see Characters::ToString ();
*/
nonvirtual Characters::String ToString () const;
private:
STDFUNCTION fFun_;
void* fOrdering_{}; // captured early when we have the right type info, so we can safely compare, and print
#if __cpp_impl_three_way_comparison < 201907
private:
template <typename FS>
friend bool operator<(const Function<FS>& lhs, const Function<FS>& rhs);
template <typename FS>
friend bool operator<= (const Function<FS>& lhs, const Function<FS>& rhs);
template <typename FS>
friend bool operator== (const Function<FS>& lhs, const Function<FS>& rhs);
template <typename FS>
friend bool operator== (const Function<FS>& lhs, nullptr_t);
template <typename FS>
friend bool operator!= (const Function<FS>& lhs, const Function<FS>& rhs);
template <typename FS>
friend bool operator!= (const Function<FS>& lhs, nullptr_t);
template <typename FS>
friend bool operator> (const Function<FS>& lhs, const Function<FS>& rhs);
template <typename FS>
friend bool operator>= (const Function<FS>& lhs, const Function<FS>& rhs);
#endif
};
#if __cpp_impl_three_way_comparison < 201907
template <typename FUNCTION_SIGNATURE>
bool operator<(const Function<FUNCTION_SIGNATURE>& lhs, const Function<FUNCTION_SIGNATURE>& rhs);
template <typename FUNCTION_SIGNATURE>
bool operator<= (const Function<FUNCTION_SIGNATURE>& lhs, const Function<FUNCTION_SIGNATURE>& rhs);
template <typename FUNCTION_SIGNATURE>
bool operator== (const Function<FUNCTION_SIGNATURE>& lhs, const Function<FUNCTION_SIGNATURE>& rhs);
template <typename FUNCTION_SIGNATURE>
bool operator== (const Function<FUNCTION_SIGNATURE>& lhs, nullptr_t);
template <typename FUNCTION_SIGNATURE>
bool operator!= (const Function<FUNCTION_SIGNATURE>& lhs, const Function<FUNCTION_SIGNATURE>& rhs);
template <typename FUNCTION_SIGNATURE>
bool operator!= (const Function<FUNCTION_SIGNATURE>& lhs, nullptr_t);
template <typename FUNCTION_SIGNATURE>
bool operator> (const Function<FUNCTION_SIGNATURE>& lhs, const Function<FUNCTION_SIGNATURE>& rhs);
template <typename FUNCTION_SIGNATURE>
bool operator>= (const Function<FUNCTION_SIGNATURE>& lhs, const Function<FUNCTION_SIGNATURE>& rhs);
#endif
}
/*
********************************************************************************
***************************** Implementation Details ***************************
********************************************************************************
*/
#include "Function.inl"
#endif /*_Stroika_Foundation_Execution_Function_h_*/