rice 4.11.4 → 4.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +26 -0
- data/CMakePresets.json +3 -3
- data/bin/rice-doc.rb +2 -0
- data/include/rice/rice.hpp +162 -113
- data/include/rice/stl.hpp +229 -69
- data/lib/mkmf-rice.rb +2 -2
- data/lib/rice/version.rb +1 -1
- data/rice/Constructor.ipp +3 -3
- data/rice/Data_Object.ipp +0 -42
- data/rice/JumpException.ipp +1 -0
- data/rice/Reference.hpp +2 -2
- data/rice/Reference.ipp +1 -1
- data/rice/cpp_api/Encoding.ipp +0 -48
- data/rice/cpp_api/Hash.ipp +19 -0
- data/rice/cpp_api/Object.hpp +2 -2
- data/rice/cpp_api/Object.ipp +3 -3
- data/rice/cpp_api/String.ipp +19 -0
- data/rice/detail/Anchor.hpp +1 -1
- data/rice/detail/Anchor.ipp +16 -10
- data/rice/detail/Parameter.ipp +11 -0
- data/rice/detail/Proc.ipp +19 -0
- data/rice/detail/Wrapper.ipp +3 -3
- data/rice/detail/from_ruby.hpp +1 -0
- data/rice/detail/to_ruby.ipp +58 -1
- data/rice/stl/function.ipp +142 -2
- data/rice/stl/map.ipp +2 -10
- data/rice/stl/multimap.ipp +2 -10
- data/rice/stl/optional.ipp +18 -0
- data/rice/stl/reference_wrapper.ipp +18 -0
- data/rice/stl/set.ipp +24 -25
- data/rice/stl/unique_ptr.ipp +3 -0
- data/rice/stl/unordered_map.ipp +2 -10
- data/rice/stl/vector.ipp +18 -15
- data/rice/traits/rice_traits.hpp +3 -0
- data/test/test_Attribute.cpp +6 -6
- data/test/test_Constructor.cpp +140 -1
- data/test/test_File.cpp +2 -3
- data/test/test_From_Ruby.cpp +3 -3
- data/test/test_Hash.cpp +8 -0
- data/test/test_Object.cpp +76 -0
- data/test/test_Overloads.cpp +74 -1
- data/test/test_Proc.cpp +11 -1
- data/test/test_Reference.cpp +20 -1
- data/test/test_Stl_Exception.cpp +2 -5
- data/test/test_Stl_Function.cpp +72 -7
- data/test/test_Stl_Map.cpp +10 -1
- data/test/test_Stl_Multimap.cpp +11 -2
- data/test/test_Stl_Optional.cpp +9 -0
- data/test/test_Stl_Reference_Wrapper.cpp +11 -0
- data/test/test_Stl_Set.cpp +12 -0
- data/test/test_Stl_Unordered_Map.cpp +10 -1
- data/test/test_Stl_Vector.cpp +130 -11
- data/test/test_String.cpp +7 -0
- data/test/test_To_Ruby.cpp +24 -1
- metadata +1 -1
data/rice/detail/Anchor.ipp
CHANGED
|
@@ -2,23 +2,28 @@ namespace Rice
|
|
|
2
2
|
{
|
|
3
3
|
namespace detail
|
|
4
4
|
{
|
|
5
|
-
inline Anchor::Anchor(VALUE value)
|
|
5
|
+
inline Anchor::Anchor(VALUE value)
|
|
6
6
|
{
|
|
7
|
+
// rb_gc_register_address() can trigger GC, so we must register the
|
|
8
|
+
// empty this->value_ slot before storing a heap VALUE in it.
|
|
9
|
+
// RB_GC_GUARD(value) keeps the ctor argument alive through the end of
|
|
10
|
+
// this method until the registered slot has been updated.
|
|
7
11
|
if (!RB_SPECIAL_CONST_P(value))
|
|
8
12
|
{
|
|
9
13
|
Anchor::registerExitHandler();
|
|
10
14
|
detail::protect(rb_gc_register_address, &this->value_);
|
|
11
15
|
this->registered_ = true;
|
|
12
16
|
}
|
|
17
|
+
this->value_ = value;
|
|
18
|
+
RB_GC_GUARD(value);
|
|
13
19
|
}
|
|
14
20
|
|
|
15
21
|
inline Anchor::~Anchor()
|
|
16
22
|
{
|
|
17
23
|
if (Anchor::enabled_ && this->registered_)
|
|
18
24
|
{
|
|
19
|
-
|
|
25
|
+
rb_gc_unregister_address(&this->value_);
|
|
20
26
|
}
|
|
21
|
-
// Ruby auto detects VALUEs in the stack, so make sure up in case this object is on the stack
|
|
22
27
|
this->registered_ = false;
|
|
23
28
|
this->value_ = Qnil;
|
|
24
29
|
}
|
|
@@ -28,17 +33,18 @@ namespace Rice
|
|
|
28
33
|
return this->value_;
|
|
29
34
|
}
|
|
30
35
|
|
|
31
|
-
// This will be called by ruby at exit - we want to disable further unregistering
|
|
32
|
-
inline void Anchor::disable(VALUE)
|
|
33
|
-
{
|
|
34
|
-
Anchor::enabled_ = false;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
36
|
inline void Anchor::registerExitHandler()
|
|
38
37
|
{
|
|
39
38
|
if (!Anchor::exitHandlerRegistered_)
|
|
40
39
|
{
|
|
41
|
-
|
|
40
|
+
// Use ruby_vm_at_exit which fires AFTER the VM is destroyed,
|
|
41
|
+
// not rb_set_end_proc which fires BEFORE. rb_set_end_proc
|
|
42
|
+
// runs as an end_proc in LIFO order alongside at_exit blocks,
|
|
43
|
+
// so its timing depends on require order — if the extension
|
|
44
|
+
// loads after minitest/autorun, the disable callback runs
|
|
45
|
+
// before tests execute, causing Anchor destructors to skip
|
|
46
|
+
// rb_gc_unregister_address and leave dangling root pointers.
|
|
47
|
+
ruby_vm_at_exit([](ruby_vm_t*) { Anchor::enabled_ = false; });
|
|
42
48
|
Anchor::exitHandlerRegistered_ = true;
|
|
43
49
|
}
|
|
44
50
|
}
|
data/rice/detail/Parameter.ipp
CHANGED
|
@@ -54,6 +54,12 @@ namespace Rice::detail
|
|
|
54
54
|
{
|
|
55
55
|
result = Convertible::None;
|
|
56
56
|
}
|
|
57
|
+
// Existing wrapped Ruby objects should prefer borrowing overloads to
|
|
58
|
+
// rvalue-reference overloads so they are not silently moved-from.
|
|
59
|
+
else if constexpr (std::is_rvalue_reference_v<T>)
|
|
60
|
+
{
|
|
61
|
+
result = Convertible::RValueMismatch;
|
|
62
|
+
}
|
|
57
63
|
// It is ok to send a non-const value to a const parameter but
|
|
58
64
|
// prefer non-const to non-const by slightly decreasing the score
|
|
59
65
|
else if (!isConst && is_const_any_v<T>)
|
|
@@ -90,6 +96,11 @@ namespace Rice::detail
|
|
|
90
96
|
{
|
|
91
97
|
return this->fromRuby_.convert(valueOpt.value());
|
|
92
98
|
}
|
|
99
|
+
else if constexpr (std::is_rvalue_reference_v<T>)
|
|
100
|
+
{
|
|
101
|
+
// Rvalue-reference parameters cannot safely use stored default values.
|
|
102
|
+
// Materializing them from std::any would require moving from shared state.
|
|
103
|
+
}
|
|
93
104
|
// Remember std::is_copy_constructible_v<std::vector<std::unique_ptr<T>>>> returns true. Sigh.
|
|
94
105
|
// So special case vector handling
|
|
95
106
|
else if constexpr (detail::is_std_vector_v<detail::intrinsic_type<T>>)
|
data/rice/detail/Proc.ipp
CHANGED
|
@@ -34,6 +34,25 @@ namespace Rice::detail
|
|
|
34
34
|
}
|
|
35
35
|
};
|
|
36
36
|
|
|
37
|
+
// Wraps a C++ function as a Ruby proc
|
|
38
|
+
template<typename Return_T, typename ...Parameter_Ts>
|
|
39
|
+
class To_Ruby<Return_T(*&)(Parameter_Ts...)>
|
|
40
|
+
{
|
|
41
|
+
public:
|
|
42
|
+
using Proc_T = Return_T(*&)(Parameter_Ts...);
|
|
43
|
+
|
|
44
|
+
To_Ruby() = default;
|
|
45
|
+
|
|
46
|
+
explicit To_Ruby(Arg*)
|
|
47
|
+
{}
|
|
48
|
+
|
|
49
|
+
VALUE convert(Proc_T proc)
|
|
50
|
+
{
|
|
51
|
+
// Wrap the C+++ function pointer as a Ruby Proc
|
|
52
|
+
return NativeProc<Proc_T>::createRubyProc(std::forward<Proc_T>(proc));
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
|
|
37
56
|
// Makes a Ruby proc callable as C callback
|
|
38
57
|
template<typename Return_T, typename ...Parameter_Ts>
|
|
39
58
|
class From_Ruby<Return_T(*)(Parameter_Ts...)>
|
data/rice/detail/Wrapper.ipp
CHANGED
|
@@ -121,10 +121,10 @@ namespace Rice::detail
|
|
|
121
121
|
|
|
122
122
|
if constexpr (is_complete_v<T>)
|
|
123
123
|
{
|
|
124
|
-
//
|
|
125
|
-
// Deleting
|
|
124
|
+
// is_polymorphic_v requires a complete type, so nest inside is_complete_v.
|
|
125
|
+
// Deleting a polymorphic class through a non-virtual destructor is UB,
|
|
126
126
|
// but it is safe if the destructor is virtual.
|
|
127
|
-
if constexpr (std::is_destructible_v<T> && (!std::
|
|
127
|
+
if constexpr (std::is_destructible_v<T> && (!std::is_polymorphic_v<T> || std::has_virtual_destructor_v<T>))
|
|
128
128
|
{
|
|
129
129
|
if (this->isOwner_)
|
|
130
130
|
{
|
data/rice/detail/from_ruby.hpp
CHANGED
|
@@ -39,6 +39,7 @@ namespace Rice::detail
|
|
|
39
39
|
static constexpr double SignedToUnsigned = 0.5;// Penalty for signed to unsigned (can't represent negatives)
|
|
40
40
|
static constexpr double FloatToInt = 0.5; // Domain change penalty when converting float to int (lossy)
|
|
41
41
|
static constexpr double ConstMismatch = 0.99; // Penalty for const mismatch
|
|
42
|
+
static constexpr double RValueMismatch = 0.98; // Prefer borrowing wrapped objects over moving from them
|
|
42
43
|
};
|
|
43
44
|
}
|
|
44
45
|
|
data/rice/detail/to_ruby.ipp
CHANGED
|
@@ -292,6 +292,25 @@ namespace Rice
|
|
|
292
292
|
Arg* arg_ = nullptr;
|
|
293
293
|
};
|
|
294
294
|
|
|
295
|
+
template<>
|
|
296
|
+
class To_Ruby<char*&>
|
|
297
|
+
{
|
|
298
|
+
public:
|
|
299
|
+
To_Ruby() = default;
|
|
300
|
+
|
|
301
|
+
explicit To_Ruby(Arg* arg) : arg_(arg)
|
|
302
|
+
{
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
VALUE convert(const char* data)
|
|
306
|
+
{
|
|
307
|
+
return To_Ruby<char*>(arg_).convert(data);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
private:
|
|
311
|
+
Arg* arg_ = nullptr;
|
|
312
|
+
};
|
|
313
|
+
|
|
295
314
|
template<int N>
|
|
296
315
|
class To_Ruby<char[N]>
|
|
297
316
|
{
|
|
@@ -324,6 +343,25 @@ namespace Rice
|
|
|
324
343
|
Arg* arg_ = nullptr;
|
|
325
344
|
};
|
|
326
345
|
|
|
346
|
+
template<int N>
|
|
347
|
+
class To_Ruby<char(&)[N]>
|
|
348
|
+
{
|
|
349
|
+
public:
|
|
350
|
+
To_Ruby() = default;
|
|
351
|
+
|
|
352
|
+
explicit To_Ruby(Arg* arg) : arg_(arg)
|
|
353
|
+
{
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
VALUE convert(const char (&buffer)[N])
|
|
357
|
+
{
|
|
358
|
+
return To_Ruby<char[N]>(arg_).convert(buffer);
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
private:
|
|
362
|
+
Arg* arg_ = nullptr;
|
|
363
|
+
};
|
|
364
|
+
|
|
327
365
|
// =========== unsigned char ============
|
|
328
366
|
template<>
|
|
329
367
|
class To_Ruby<unsigned char>
|
|
@@ -1045,6 +1083,25 @@ namespace Rice
|
|
|
1045
1083
|
Arg* arg_ = nullptr;
|
|
1046
1084
|
};
|
|
1047
1085
|
|
|
1086
|
+
template<>
|
|
1087
|
+
class To_Ruby<std::nullptr_t&>
|
|
1088
|
+
{
|
|
1089
|
+
public:
|
|
1090
|
+
To_Ruby() = default;
|
|
1091
|
+
|
|
1092
|
+
explicit To_Ruby(Arg* arg) : arg_(arg)
|
|
1093
|
+
{
|
|
1094
|
+
}
|
|
1095
|
+
|
|
1096
|
+
VALUE convert(std::nullptr_t const)
|
|
1097
|
+
{
|
|
1098
|
+
return Qnil;
|
|
1099
|
+
}
|
|
1100
|
+
|
|
1101
|
+
private:
|
|
1102
|
+
Arg* arg_ = nullptr;
|
|
1103
|
+
};
|
|
1104
|
+
|
|
1048
1105
|
// =========== void ============
|
|
1049
1106
|
template<>
|
|
1050
1107
|
class To_Ruby<void>
|
|
@@ -1102,4 +1159,4 @@ namespace Rice
|
|
|
1102
1159
|
Arg* arg_ = nullptr;
|
|
1103
1160
|
};
|
|
1104
1161
|
}
|
|
1105
|
-
}
|
|
1162
|
+
}
|
data/rice/stl/function.ipp
CHANGED
|
@@ -24,9 +24,9 @@ namespace Rice::stl
|
|
|
24
24
|
klass_.define_method("initialize", [](VALUE self, VALUE callable) -> void
|
|
25
25
|
{
|
|
26
26
|
// Create std::function that wraps the Ruby callable
|
|
27
|
-
Function_T* data = new Function_T([callable](auto
|
|
27
|
+
Function_T* data = new Function_T([callable](auto&&... args)
|
|
28
28
|
{
|
|
29
|
-
Object result = Object(callable).call("call", args...);
|
|
29
|
+
Object result = Object(callable).call("call", std::forward<decltype(args)>(args)...);
|
|
30
30
|
|
|
31
31
|
using Return_T = typename Function_T::result_type;
|
|
32
32
|
if constexpr (!std::is_void_v<Return_T>)
|
|
@@ -84,6 +84,146 @@ namespace Rice
|
|
|
84
84
|
|
|
85
85
|
namespace Rice::detail
|
|
86
86
|
{
|
|
87
|
+
template<typename Return_T, typename ...Parameter_Ts>
|
|
88
|
+
inline std::function<Return_T(Parameter_Ts...)> makeRubyFunction(VALUE value)
|
|
89
|
+
{
|
|
90
|
+
Pin proc(value);
|
|
91
|
+
|
|
92
|
+
return [proc = std::move(proc)](Parameter_Ts... args) -> Return_T
|
|
93
|
+
{
|
|
94
|
+
Object result = Object(proc.value()).call("call", std::forward<Parameter_Ts>(args)...);
|
|
95
|
+
|
|
96
|
+
if constexpr (!std::is_void_v<Return_T>)
|
|
97
|
+
{
|
|
98
|
+
return From_Ruby<std::remove_cv_t<Return_T>>().convert(result);
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
template<typename Return_T, typename ...Parameter_Ts>
|
|
104
|
+
class From_Ruby<std::function<Return_T(Parameter_Ts...)>>
|
|
105
|
+
{
|
|
106
|
+
public:
|
|
107
|
+
using Function_T = std::function<Return_T(Parameter_Ts...)>;
|
|
108
|
+
|
|
109
|
+
From_Ruby() = default;
|
|
110
|
+
|
|
111
|
+
explicit From_Ruby(Arg* arg) : arg_(arg)
|
|
112
|
+
{
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
double is_convertible(VALUE value)
|
|
116
|
+
{
|
|
117
|
+
switch (rb_type(value))
|
|
118
|
+
{
|
|
119
|
+
case RUBY_T_DATA:
|
|
120
|
+
return Data_Type<Function_T>::is_descendant(value) ? Convertible::Exact : Convertible::None;
|
|
121
|
+
default:
|
|
122
|
+
return protect(rb_obj_is_proc, value) == Qtrue ? Convertible::ConstMismatch : Convertible::None;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
Function_T convert(VALUE value)
|
|
127
|
+
{
|
|
128
|
+
if (Data_Type<Function_T>::is_descendant(value))
|
|
129
|
+
{
|
|
130
|
+
return *detail::unwrap<Function_T>(value, Data_Type<Function_T>::ruby_data_type(), false);
|
|
131
|
+
}
|
|
132
|
+
else if (protect(rb_obj_is_proc, value) == Qtrue)
|
|
133
|
+
{
|
|
134
|
+
return makeRubyFunction<Return_T, Parameter_Ts...>(value);
|
|
135
|
+
}
|
|
136
|
+
else
|
|
137
|
+
{
|
|
138
|
+
throw Exception(rb_eTypeError, "wrong argument type %s (expected %s)",
|
|
139
|
+
detail::protect(rb_obj_classname, value), "std::function");
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
private:
|
|
144
|
+
Arg* arg_ = nullptr;
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
template<typename Return_T, typename ...Parameter_Ts>
|
|
148
|
+
class From_Ruby<std::function<Return_T(Parameter_Ts...)>&>
|
|
149
|
+
{
|
|
150
|
+
public:
|
|
151
|
+
using Function_T = std::function<Return_T(Parameter_Ts...)>;
|
|
152
|
+
|
|
153
|
+
From_Ruby() = default;
|
|
154
|
+
|
|
155
|
+
explicit From_Ruby(Arg* arg) : arg_(arg)
|
|
156
|
+
{
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
double is_convertible(VALUE value)
|
|
160
|
+
{
|
|
161
|
+
return From_Ruby<Function_T>(arg_).is_convertible(value);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
Function_T& convert(VALUE value)
|
|
165
|
+
{
|
|
166
|
+
if (Data_Type<Function_T>::is_descendant(value))
|
|
167
|
+
{
|
|
168
|
+
return *detail::unwrap<Function_T>(value, Data_Type<Function_T>::ruby_data_type(), false);
|
|
169
|
+
}
|
|
170
|
+
else if (protect(rb_obj_is_proc, value) == Qtrue)
|
|
171
|
+
{
|
|
172
|
+
converted_ = makeRubyFunction<Return_T, Parameter_Ts...>(value);
|
|
173
|
+
return converted_;
|
|
174
|
+
}
|
|
175
|
+
else
|
|
176
|
+
{
|
|
177
|
+
throw Exception(rb_eTypeError, "wrong argument type %s (expected %s)",
|
|
178
|
+
detail::protect(rb_obj_classname, value), "std::function");
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
private:
|
|
183
|
+
Arg* arg_ = nullptr;
|
|
184
|
+
Function_T converted_;
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
template<typename Return_T, typename ...Parameter_Ts>
|
|
188
|
+
class From_Ruby<std::function<Return_T(Parameter_Ts...)>&&>
|
|
189
|
+
{
|
|
190
|
+
public:
|
|
191
|
+
using Function_T = std::function<Return_T(Parameter_Ts...)>;
|
|
192
|
+
|
|
193
|
+
From_Ruby() = default;
|
|
194
|
+
|
|
195
|
+
explicit From_Ruby(Arg* arg) : arg_(arg)
|
|
196
|
+
{
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
double is_convertible(VALUE value)
|
|
200
|
+
{
|
|
201
|
+
return From_Ruby<Function_T>(arg_).is_convertible(value);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
Function_T&& convert(VALUE value)
|
|
205
|
+
{
|
|
206
|
+
if (Data_Type<Function_T>::is_descendant(value))
|
|
207
|
+
{
|
|
208
|
+
return std::move(*detail::unwrap<Function_T>(value, Data_Type<Function_T>::ruby_data_type(), false));
|
|
209
|
+
}
|
|
210
|
+
else if (protect(rb_obj_is_proc, value) == Qtrue)
|
|
211
|
+
{
|
|
212
|
+
converted_ = makeRubyFunction<Return_T, Parameter_Ts...>(value);
|
|
213
|
+
return std::move(converted_);
|
|
214
|
+
}
|
|
215
|
+
else
|
|
216
|
+
{
|
|
217
|
+
throw Exception(rb_eTypeError, "wrong argument type %s (expected %s)",
|
|
218
|
+
detail::protect(rb_obj_classname, value), "std::function");
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
private:
|
|
223
|
+
Arg* arg_ = nullptr;
|
|
224
|
+
Function_T converted_;
|
|
225
|
+
};
|
|
226
|
+
|
|
87
227
|
template<typename Signature_T>
|
|
88
228
|
struct Type<std::function<Signature_T>>
|
|
89
229
|
{
|
data/rice/stl/map.ipp
CHANGED
|
@@ -124,16 +124,8 @@ namespace Rice
|
|
|
124
124
|
return it != map.end();
|
|
125
125
|
}, Arg("value"));
|
|
126
126
|
rb_define_alias(klass_, "eql?", "==");
|
|
127
|
+
rb_define_alias(klass_, "has_value", "value?");
|
|
127
128
|
}
|
|
128
|
-
else
|
|
129
|
-
{
|
|
130
|
-
klass_.define_method("value?", [](T&, Mapped_Parameter_T) -> bool
|
|
131
|
-
{
|
|
132
|
-
return false;
|
|
133
|
-
}, Arg("value"));
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
rb_define_alias(klass_, "has_value", "value?");
|
|
137
129
|
}
|
|
138
130
|
|
|
139
131
|
void define_modify_methods()
|
|
@@ -465,4 +457,4 @@ namespace Rice
|
|
|
465
457
|
std::map<T, U> converted_;
|
|
466
458
|
};
|
|
467
459
|
}
|
|
468
|
-
}
|
|
460
|
+
}
|
data/rice/stl/multimap.ipp
CHANGED
|
@@ -123,16 +123,8 @@ namespace Rice
|
|
|
123
123
|
return it != multimap.end();
|
|
124
124
|
}, Arg("value"));
|
|
125
125
|
rb_define_alias(klass_, "eql?", "==");
|
|
126
|
+
rb_define_alias(klass_, "has_value", "value?");
|
|
126
127
|
}
|
|
127
|
-
else
|
|
128
|
-
{
|
|
129
|
-
klass_.define_method("value?", [](T&, Mapped_Parameter_T) -> bool
|
|
130
|
-
{
|
|
131
|
-
return false;
|
|
132
|
-
}, Arg("value"));
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
rb_define_alias(klass_, "has_value", "value?");
|
|
136
128
|
}
|
|
137
129
|
|
|
138
130
|
void define_modify_methods()
|
|
@@ -445,4 +437,4 @@ namespace Rice
|
|
|
445
437
|
std::multimap<T, U> converted_;
|
|
446
438
|
};
|
|
447
439
|
}
|
|
448
|
-
}
|
|
440
|
+
}
|
data/rice/stl/optional.ipp
CHANGED
|
@@ -36,6 +36,24 @@ namespace Rice::detail
|
|
|
36
36
|
Arg* arg_ = nullptr;
|
|
37
37
|
};
|
|
38
38
|
|
|
39
|
+
template<>
|
|
40
|
+
class To_Ruby<std::nullopt_t&>
|
|
41
|
+
{
|
|
42
|
+
public:
|
|
43
|
+
To_Ruby() = default;
|
|
44
|
+
|
|
45
|
+
explicit To_Ruby(Arg* arg) : arg_(arg)
|
|
46
|
+
{}
|
|
47
|
+
|
|
48
|
+
VALUE convert(const std::nullopt_t&)
|
|
49
|
+
{
|
|
50
|
+
return Qnil;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
private:
|
|
54
|
+
Arg* arg_ = nullptr;
|
|
55
|
+
};
|
|
56
|
+
|
|
39
57
|
template<typename T>
|
|
40
58
|
class To_Ruby<std::optional<T>>
|
|
41
59
|
{
|
|
@@ -36,6 +36,24 @@ namespace Rice::detail
|
|
|
36
36
|
Arg* arg_ = nullptr;
|
|
37
37
|
};
|
|
38
38
|
|
|
39
|
+
template<typename T>
|
|
40
|
+
class To_Ruby<std::reference_wrapper<T>&>
|
|
41
|
+
{
|
|
42
|
+
public:
|
|
43
|
+
To_Ruby() = default;
|
|
44
|
+
|
|
45
|
+
explicit To_Ruby(Arg* arg) : arg_(arg)
|
|
46
|
+
{}
|
|
47
|
+
|
|
48
|
+
VALUE convert(const std::reference_wrapper<T>& data)
|
|
49
|
+
{
|
|
50
|
+
return To_Ruby<T&>().convert(data.get());
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
private:
|
|
54
|
+
Arg* arg_ = nullptr;
|
|
55
|
+
};
|
|
56
|
+
|
|
39
57
|
template<typename T>
|
|
40
58
|
class From_Ruby<std::reference_wrapper<T>>
|
|
41
59
|
{
|
data/rice/stl/set.ipp
CHANGED
|
@@ -101,23 +101,23 @@ namespace Rice
|
|
|
101
101
|
|
|
102
102
|
void define_operators()
|
|
103
103
|
{
|
|
104
|
-
klass_
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
104
|
+
klass_.define_method("<<", [](T& self, Parameter_T value) -> T&
|
|
105
|
+
{
|
|
106
|
+
self.insert(value);
|
|
107
|
+
return self;
|
|
108
|
+
}, Arg("value").keepAlive());
|
|
109
|
+
|
|
110
|
+
if constexpr (detail::is_comparable_v<Value_T>)
|
|
111
|
+
{
|
|
112
|
+
klass_.define_method("==", [](const T& self, const T& other) -> bool
|
|
111
113
|
{
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
}
|
|
120
|
-
}, Arg("other"))
|
|
114
|
+
return self == other;
|
|
115
|
+
}, Arg("other"));
|
|
116
|
+
|
|
117
|
+
rb_define_alias(klass_, "eql?", "==");
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
klass_
|
|
121
121
|
.define_method("&", [](const T& self, const T& other) -> T
|
|
122
122
|
{
|
|
123
123
|
T result;
|
|
@@ -164,15 +164,14 @@ namespace Rice
|
|
|
164
164
|
return std::includes(self.begin(), self.end(),
|
|
165
165
|
other.begin(), other.end());
|
|
166
166
|
}, Arg("other"));
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
rb_define_alias(klass_, "superset?", ">");
|
|
167
|
+
|
|
168
|
+
rb_define_alias(klass_, "intersection", "&");
|
|
169
|
+
rb_define_alias(klass_, "union", "|");
|
|
170
|
+
rb_define_alias(klass_, "difference", "-");
|
|
171
|
+
rb_define_alias(klass_, "proper_subset?", "<");
|
|
172
|
+
rb_define_alias(klass_, "subset?", "<");
|
|
173
|
+
rb_define_alias(klass_, "proper_superset?", ">");
|
|
174
|
+
rb_define_alias(klass_, "superset?", ">");
|
|
176
175
|
}
|
|
177
176
|
|
|
178
177
|
void define_enumerable()
|
data/rice/stl/unique_ptr.ipp
CHANGED
|
@@ -5,6 +5,9 @@ namespace Rice
|
|
|
5
5
|
template<typename T>
|
|
6
6
|
Data_Type<std::unique_ptr<T>> define_unique_ptr(std::string klassName)
|
|
7
7
|
{
|
|
8
|
+
static_assert(detail::is_complete_v<T>,
|
|
9
|
+
"Rice does not support binding std::unique_ptr<T> when T is incomplete.");
|
|
10
|
+
|
|
8
11
|
using UniquePtr_T = std::unique_ptr<T>;
|
|
9
12
|
using Data_Type_T = Data_Type<UniquePtr_T>;
|
|
10
13
|
|
data/rice/stl/unordered_map.ipp
CHANGED
|
@@ -124,16 +124,8 @@ namespace Rice
|
|
|
124
124
|
return it != unordered_map.end();
|
|
125
125
|
}, Arg("value"));
|
|
126
126
|
rb_define_alias(klass_, "eql?", "==");
|
|
127
|
+
rb_define_alias(klass_, "has_value", "value?");
|
|
127
128
|
}
|
|
128
|
-
else
|
|
129
|
-
{
|
|
130
|
-
klass_.define_method("value?", [](T&, Mapped_Parameter_T) -> bool
|
|
131
|
-
{
|
|
132
|
-
return false;
|
|
133
|
-
}, Arg("value"));
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
rb_define_alias(klass_, "has_value", "value?");
|
|
137
129
|
}
|
|
138
130
|
|
|
139
131
|
void define_modify_methods()
|
|
@@ -465,4 +457,4 @@ namespace Rice
|
|
|
465
457
|
std::unordered_map<T, U> converted_;
|
|
466
458
|
};
|
|
467
459
|
}
|
|
468
|
-
}
|
|
460
|
+
}
|
data/rice/stl/vector.ipp
CHANGED
|
@@ -296,21 +296,6 @@ namespace Rice
|
|
|
296
296
|
}, Arg("value"));
|
|
297
297
|
rb_define_alias(klass_, "eql?", "==");
|
|
298
298
|
}
|
|
299
|
-
else
|
|
300
|
-
{
|
|
301
|
-
klass_.define_method("delete", [](T&, Parameter_T) -> std::optional<Value_T>
|
|
302
|
-
{
|
|
303
|
-
return std::nullopt;
|
|
304
|
-
}, Arg("value"))
|
|
305
|
-
.define_method("include?", [](const T&, Parameter_T)
|
|
306
|
-
{
|
|
307
|
-
return false;
|
|
308
|
-
}, Arg("value"))
|
|
309
|
-
.define_method("index", [](const T&, Parameter_T) -> std::optional<Difference_T>
|
|
310
|
-
{
|
|
311
|
-
return std::nullopt;
|
|
312
|
-
}, Arg("value"));
|
|
313
|
-
}
|
|
314
299
|
}
|
|
315
300
|
|
|
316
301
|
void define_modify_methods()
|
|
@@ -721,5 +706,23 @@ namespace Rice
|
|
|
721
706
|
private:
|
|
722
707
|
Arg* arg_ = nullptr;
|
|
723
708
|
};
|
|
709
|
+
|
|
710
|
+
template<>
|
|
711
|
+
class To_Ruby<std::vector<bool>::reference&>
|
|
712
|
+
{
|
|
713
|
+
public:
|
|
714
|
+
To_Ruby() = default;
|
|
715
|
+
|
|
716
|
+
explicit To_Ruby(Arg* arg) : arg_(arg)
|
|
717
|
+
{}
|
|
718
|
+
|
|
719
|
+
VALUE convert(const std::vector<bool>::reference& value)
|
|
720
|
+
{
|
|
721
|
+
return value ? Qtrue : Qfalse;
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
private:
|
|
725
|
+
Arg* arg_ = nullptr;
|
|
726
|
+
};
|
|
724
727
|
}
|
|
725
728
|
}
|
data/rice/traits/rice_traits.hpp
CHANGED
|
@@ -81,6 +81,9 @@ namespace Rice
|
|
|
81
81
|
constexpr bool is_ostreamable_v = is_ostreamable<T>::value;
|
|
82
82
|
|
|
83
83
|
// Is the type comparable?
|
|
84
|
+
// Libraries with unconstrained operator== declarations may specialize this
|
|
85
|
+
// trait to false when equality is not actually usable by Rice's STL
|
|
86
|
+
// wrappers.
|
|
84
87
|
template<typename T, typename SFINAE = void>
|
|
85
88
|
struct is_comparable : std::false_type {};
|
|
86
89
|
|
data/test/test_Attribute.cpp
CHANGED
|
@@ -306,13 +306,13 @@ TESTCASE(not_assignable)
|
|
|
306
306
|
//);
|
|
307
307
|
|
|
308
308
|
c.define_attr("not_assignable", &DataStruct::notAssignable, AttrAccess::Read);
|
|
309
|
-
|
|
309
|
+
Object notAssignable = notAssignableClass.call("new");
|
|
310
310
|
|
|
311
|
-
|
|
311
|
+
Object dataStruct = c.call("new");
|
|
312
312
|
|
|
313
313
|
ASSERT_EXCEPTION_CHECK(
|
|
314
314
|
Exception,
|
|
315
|
-
|
|
315
|
+
dataStruct.call("not_assignable=", notAssignable),
|
|
316
316
|
ASSERT_MATCH(R"(undefined method (`|')not_assignable=')", ex.what())
|
|
317
317
|
);
|
|
318
318
|
}
|
|
@@ -333,13 +333,13 @@ TESTCASE(not_copyable)
|
|
|
333
333
|
//);
|
|
334
334
|
|
|
335
335
|
c.define_attr("not_copyable", &DataStruct::notCopyable, AttrAccess::Read);
|
|
336
|
-
|
|
336
|
+
Object notCopyable = notCopyableClass.call("new");
|
|
337
337
|
|
|
338
|
-
|
|
338
|
+
Object dataStruct = c.call("new");
|
|
339
339
|
|
|
340
340
|
ASSERT_EXCEPTION_CHECK(
|
|
341
341
|
Exception,
|
|
342
|
-
|
|
342
|
+
dataStruct.call("not_assignable=", notCopyable),
|
|
343
343
|
ASSERT_MATCH(R"(undefined method (`|')not_assignable=')", ex.what())
|
|
344
344
|
);
|
|
345
345
|
}
|