rice 4.8.0 → 4.9.1

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.
Files changed (68) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +25 -1
  3. data/CMakePresets.json +77 -50
  4. data/FindRuby.cmake +1 -1
  5. data/bin/rice-doc.rb +2 -0
  6. data/include/rice/api.hpp +14 -1
  7. data/include/rice/rice.hpp +351 -132
  8. data/include/rice/stl.hpp +319 -256
  9. data/lib/rice/doc/config.rb +57 -57
  10. data/lib/rice/doc/cpp_reference.rb +158 -158
  11. data/lib/rice/doc/doxygen.rb +289 -289
  12. data/lib/rice/doc/mkdocs.rb +332 -332
  13. data/lib/rice/doc/rice.rb +48 -47
  14. data/lib/rice/doc/ruby.rb +26 -26
  15. data/lib/rice/native.rb +15 -15
  16. data/lib/rice/native_registry.rb +12 -17
  17. data/lib/rice/parameter.rb +5 -5
  18. data/lib/rice/rbs.rb +72 -72
  19. data/lib/rice/version.rb +1 -1
  20. data/lib/rubygems/builder.rb +9 -9
  21. data/lib/rubygems_plugin.rb +8 -8
  22. data/rice/Data_Type.ipp +12 -7
  23. data/rice/cpp_api/Class.hpp +5 -0
  24. data/rice/cpp_api/Class.ipp +5 -0
  25. data/rice/cpp_api/Object.hpp +6 -0
  26. data/rice/cpp_api/Object.ipp +5 -0
  27. data/rice/detail/Forwards.hpp +18 -0
  28. data/rice/detail/Forwards.ipp +60 -0
  29. data/rice/detail/Native.ipp +2 -4
  30. data/rice/detail/NativeAttributeGet.ipp +1 -1
  31. data/rice/detail/NativeAttributeSet.hpp +5 -3
  32. data/rice/detail/NativeAttributeSet.ipp +41 -33
  33. data/rice/detail/NativeMethod.ipp +25 -22
  34. data/rice/detail/NativeRegistry.hpp +4 -2
  35. data/rice/detail/NativeRegistry.ipp +42 -9
  36. data/rice/detail/Parameter.ipp +3 -4
  37. data/rice/detail/Type.ipp +4 -0
  38. data/rice/detail/Wrapper.hpp +17 -12
  39. data/rice/detail/Wrapper.ipp +95 -36
  40. data/rice/rice.hpp +3 -0
  41. data/rice/rice_api/NativeRegistry.ipp +14 -1
  42. data/rice/stl/exception.ipp +1 -1
  43. data/rice/stl/filesystem.ipp +1 -1
  44. data/rice/stl/map.ipp +13 -11
  45. data/rice/stl/multimap.ipp +13 -11
  46. data/rice/stl/pair.ipp +14 -8
  47. data/rice/stl/set.ipp +16 -16
  48. data/rice/stl/shared_ptr.hpp +16 -0
  49. data/rice/stl/shared_ptr.ipp +74 -37
  50. data/rice/stl/type_index.ipp +1 -1
  51. data/rice/stl/unique_ptr.hpp +9 -3
  52. data/rice/stl/unique_ptr.ipp +80 -124
  53. data/rice/stl/unordered_map.ipp +14 -12
  54. data/rice/stl/vector.ipp +67 -31
  55. data/test/test_Attribute.cpp +72 -0
  56. data/test/test_Callback.cpp +3 -0
  57. data/test/test_Inheritance.cpp +14 -14
  58. data/test/test_Keep_Alive_No_Wrapper.cpp +6 -2
  59. data/test/test_Stl_Map.cpp +46 -0
  60. data/test/test_Stl_Multimap.cpp +46 -0
  61. data/test/test_Stl_Set.cpp +34 -0
  62. data/test/test_Stl_SharedPtr.cpp +160 -45
  63. data/test/test_Stl_UniquePtr.cpp +48 -3
  64. data/test/test_Stl_Unordered_Map.cpp +46 -0
  65. data/test/test_Stl_Variant.cpp +10 -14
  66. data/test/test_Stl_Vector.cpp +140 -13
  67. data/test/test_Tracking.cpp +3 -0
  68. metadata +3 -1
@@ -2,6 +2,22 @@
2
2
 
3
3
  namespace Rice::detail
4
4
  {
5
+ inline void WrapperBase::addKeepAlive(VALUE object, VALUE keepAlive)
6
+ {
7
+ WrapperBase* wrapper = getWrapper(object);
8
+ wrapper->addKeepAlive(keepAlive);
9
+ }
10
+
11
+ inline bool WrapperBase::isConst(VALUE object)
12
+ {
13
+ WrapperBase* wrapper = getWrapper(object);
14
+ return wrapper->isConst();
15
+ }
16
+
17
+ inline WrapperBase::WrapperBase(rb_data_type_t* rb_data_type) : rb_data_type_(rb_data_type)
18
+ {
19
+ }
20
+
5
21
  inline bool WrapperBase::isConst()
6
22
  {
7
23
  return this->isConst_;
@@ -27,31 +43,40 @@ namespace Rice::detail
27
43
 
28
44
  // ---- Wrapper -----
29
45
  template <typename T>
30
- inline Wrapper<T>::Wrapper(T& data): data_(data)
46
+ inline Wrapper<T>::Wrapper(rb_data_type_t* rb_data_type, T& data) : WrapperBase(rb_data_type), data_(data)
31
47
  {
32
48
  this->isConst_ = std::is_const_v<std::remove_reference_t<T>>;
33
49
  }
34
50
 
35
51
  template <typename T>
36
- inline Wrapper<T>::Wrapper(T&& data) : data_(std::move(data))
52
+ inline Wrapper<T>::Wrapper(rb_data_type_t* rb_data_type, T&& data) : WrapperBase(rb_data_type), data_(std::move(data))
37
53
  {
38
54
  }
39
55
 
40
56
  template <typename T>
41
57
  inline Wrapper<T>::~Wrapper()
42
58
  {
43
- Registries::instance.instances.remove(this->get());
59
+ Registries::instance.instances.remove(this->get(this->rb_data_type_));
44
60
  }
45
61
 
46
62
  template <typename T>
47
- inline void* Wrapper<T>::Wrapper::get()
63
+ inline void* Wrapper<T>::get(rb_data_type_t* requestedType)
48
64
  {
49
- return (void*)&this->data_;
65
+ if (rb_typeddata_inherited_p(this->rb_data_type_, requestedType))
66
+ {
67
+ return (void*)&this->data_;
68
+ }
69
+ else
70
+ {
71
+ throw Exception(rb_eTypeError, "wrong argument type %s (expected %s)",
72
+ this->rb_data_type_->wrap_struct_name,
73
+ requestedType->wrap_struct_name);
74
+ }
50
75
  }
51
76
 
52
77
  // ---- Wrapper& -----
53
78
  template <typename T>
54
- inline Wrapper<T&>::Wrapper(T& data): data_(data)
79
+ inline Wrapper<T&>::Wrapper(rb_data_type_t* rb_data_type, T& data) : WrapperBase(rb_data_type), data_(data)
55
80
  {
56
81
  this->isConst_ = std::is_const_v<std::remove_reference_t<T>>;
57
82
  }
@@ -59,18 +84,27 @@ namespace Rice::detail
59
84
  template <typename T>
60
85
  inline Wrapper<T&>::~Wrapper()
61
86
  {
62
- Registries::instance.instances.remove(this->get());
87
+ Registries::instance.instances.remove(this->get(this->rb_data_type_));
63
88
  }
64
89
 
65
90
  template <typename T>
66
- inline void* Wrapper<T&>::get()
91
+ inline void* Wrapper<T&>::get(rb_data_type_t* requestedType)
67
92
  {
68
- return (void*)&this->data_;
93
+ if (rb_typeddata_inherited_p(this->rb_data_type_, requestedType))
94
+ {
95
+ return (void*)&this->data_;
96
+ }
97
+ else
98
+ {
99
+ throw Exception(rb_eTypeError, "wrong argument type %s (expected %s)",
100
+ this->rb_data_type_->wrap_struct_name,
101
+ requestedType->wrap_struct_name);
102
+ }
69
103
  }
70
104
 
71
105
  // ---- Wrapper* -----
72
106
  template <typename T>
73
- inline Wrapper<T*>::Wrapper(T* data, bool isOwner) : data_(data)
107
+ inline Wrapper<T*>::Wrapper(rb_data_type_t* rb_data_type, T* data, bool isOwner) : WrapperBase(rb_data_type), data_(data)
74
108
  {
75
109
  this->isOwner_ = isOwner;
76
110
  this->isConst_ = std::is_const_v<std::remove_pointer_t<T>>;
@@ -79,7 +113,8 @@ namespace Rice::detail
79
113
  template <typename T>
80
114
  inline Wrapper<T*>::~Wrapper()
81
115
  {
82
- Registries::instance.instances.remove(this->get());
116
+ Registries::instance.instances.remove(this->get(this->rb_data_type_));
117
+
83
118
  if constexpr (std::is_destructible_v<T>)
84
119
  {
85
120
  if (this->isOwner_)
@@ -90,14 +125,23 @@ namespace Rice::detail
90
125
  }
91
126
 
92
127
  template <typename T>
93
- inline void* Wrapper<T*>::get()
128
+ inline void* Wrapper<T*>::get(rb_data_type_t* requestedType)
94
129
  {
95
- return (void*)this->data_;
130
+ if (rb_typeddata_inherited_p(this->rb_data_type_, requestedType))
131
+ {
132
+ return (void*)this->data_;
133
+ }
134
+ else
135
+ {
136
+ throw Exception(rb_eTypeError, "wrong argument type %s (expected %s)",
137
+ this->rb_data_type_->wrap_struct_name,
138
+ requestedType->wrap_struct_name);
139
+ }
96
140
  }
97
141
 
98
142
  // ---- Wrapper** -----
99
143
  template <typename T>
100
- inline Wrapper<T**>::Wrapper(T** data, bool isOwner) : data_(data)
144
+ inline Wrapper<T**>::Wrapper(rb_data_type_t* rb_data_type, T** data, bool isOwner) : WrapperBase(rb_data_type), data_(data)
101
145
  {
102
146
  this->isOwner_ = isOwner;
103
147
  this->isConst_ = std::is_const_v<std::remove_pointer_t<std::remove_pointer_t<T>>>;
@@ -106,7 +150,8 @@ namespace Rice::detail
106
150
  template <typename T>
107
151
  inline Wrapper<T**>::~Wrapper()
108
152
  {
109
- Registries::instance.instances.remove(this->get());
153
+ Registries::instance.instances.remove(this->get(this->rb_data_type_));
154
+
110
155
  if constexpr (std::is_destructible_v<T>)
111
156
  {
112
157
  if (this->isOwner_)
@@ -117,9 +162,18 @@ namespace Rice::detail
117
162
  }
118
163
 
119
164
  template <typename T>
120
- inline void* Wrapper<T**>::get()
165
+ inline void* Wrapper<T**>::get(rb_data_type_t* requestedType)
121
166
  {
122
- return (void*)this->data_;
167
+ if (rb_typeddata_inherited_p(this->rb_data_type_, requestedType))
168
+ {
169
+ return (void*)this->data_;
170
+ }
171
+ else
172
+ {
173
+ throw Exception(rb_eTypeError, "wrong argument type %s (expected %s)",
174
+ this->rb_data_type_->wrap_struct_name,
175
+ requestedType->wrap_struct_name);
176
+ }
123
177
  }
124
178
 
125
179
  // ---- Helper Functions -------
@@ -136,7 +190,7 @@ namespace Rice::detail
136
190
  // If Ruby is not the owner then wrap the reference
137
191
  if (!isOwner)
138
192
  {
139
- wrapper = new Wrapper<T&>(data);
193
+ wrapper = new Wrapper<T&>(rb_data_type, data);
140
194
  result = TypedData_Wrap_Struct(klass, rb_data_type, wrapper);
141
195
  }
142
196
 
@@ -145,12 +199,12 @@ namespace Rice::detail
145
199
  {
146
200
  if constexpr (std::is_copy_constructible_v<typename T::value_type>)
147
201
  {
148
- wrapper = new Wrapper<T>(data);
202
+ wrapper = new Wrapper<T>(rb_data_type, data);
149
203
  result = TypedData_Wrap_Struct(klass, rb_data_type, wrapper);
150
204
  }
151
205
  else
152
206
  {
153
- wrapper = new Wrapper<T>(std::move(data));
207
+ wrapper = new Wrapper<T>(rb_data_type, std::move(data));
154
208
  result = TypedData_Wrap_Struct(klass, rb_data_type, wrapper);
155
209
  }
156
210
  }
@@ -158,14 +212,14 @@ namespace Rice::detail
158
212
  // Ruby is the owner so copy data
159
213
  else if constexpr (std::is_copy_constructible_v<T>)
160
214
  {
161
- wrapper = new Wrapper<T>(data);
215
+ wrapper = new Wrapper<T>(rb_data_type, data);
162
216
  result = TypedData_Wrap_Struct(klass, rb_data_type, wrapper);
163
217
  }
164
218
 
165
219
  // Ruby is the owner so move data
166
220
  else if constexpr (std::is_move_constructible_v<T>)
167
221
  {
168
- wrapper = new Wrapper<T>(std::move(data));
222
+ wrapper = new Wrapper<T>(rb_data_type, std::move(data));
169
223
  result = TypedData_Wrap_Struct(klass, rb_data_type, wrapper);
170
224
  }
171
225
 
@@ -177,7 +231,7 @@ namespace Rice::detail
177
231
  throw std::runtime_error(message);
178
232
  }
179
233
 
180
- Registries::instance.instances.add(wrapper->get(), result);
234
+ Registries::instance.instances.add(wrapper->get(rb_data_type), result);
181
235
 
182
236
  return result;
183
237
  };
@@ -190,38 +244,40 @@ namespace Rice::detail
190
244
  if (result != Qnil)
191
245
  return result;
192
246
 
193
- WrapperBase* wrapper = new Wrapper<T*>(data, isOwner);
247
+ WrapperBase* wrapper = new Wrapper<T*>(rb_data_type, data, isOwner);
194
248
  result = TypedData_Wrap_Struct(klass, rb_data_type, wrapper);
195
249
 
196
- Registries::instance.instances.add(wrapper->get(), result);
250
+ Registries::instance.instances.add(wrapper->get(rb_data_type), result);
197
251
  return result;
198
252
  };
199
253
 
200
254
  template <typename T>
201
255
  inline T* unwrap(VALUE value, rb_data_type_t* rb_data_type, bool takeOwnership)
202
256
  {
203
- if (rb_type(value) != RUBY_T_DATA)
257
+ if (!RTYPEDDATA_P(value))
204
258
  {
205
259
  std::string message = "The Ruby object does not wrap a C++ object. It is actually a " +
206
260
  std::string(detail::protect(rb_obj_classname, value)) + ".";
207
261
  throw std::runtime_error(message);
208
262
  }
209
263
 
210
- WrapperBase* wrapper = getWrapper(value, rb_data_type);
264
+ WrapperBase* wrapper = static_cast<WrapperBase*>(RTYPEDDATA_DATA(value));
211
265
 
212
266
  if (wrapper == nullptr)
213
267
  {
214
- std::string message = "Wrapped C++ object is nil. Did you override " +
215
- std::string(detail::protect(rb_obj_classname, value)) +
268
+ std::string message = "Wrapped C++ object is nil. Did you override " +
269
+ std::string(detail::protect(rb_obj_classname, value)) +
216
270
  "#initialize and forget to call super?";
217
271
 
218
272
  throw std::runtime_error(message);
219
273
  }
220
274
 
221
275
  if (takeOwnership)
276
+ {
222
277
  wrapper->setOwner(false);
278
+ }
223
279
 
224
- return static_cast<T*>(wrapper->get());
280
+ return static_cast<T*>(wrapper->get(rb_data_type));
225
281
  }
226
282
 
227
283
  template <typename Wrapper_T>
@@ -243,7 +299,8 @@ namespace Rice::detail
243
299
  if (!RTYPEDDATA_P(value))
244
300
  {
245
301
  throw Exception(rb_eTypeError, "wrong argument type %s (expected %s)",
246
- detail::protect(rb_obj_classname, value), "wrapped C++ object");
302
+ detail::protect(rb_obj_classname, value),
303
+ "wrapped C++ object");
247
304
  }
248
305
 
249
306
  return static_cast<WrapperBase*>(RTYPEDDATA_DATA(value));
@@ -254,21 +311,23 @@ namespace Rice::detail
254
311
  }
255
312
 
256
313
  template <typename T>
257
- inline void wrapConstructed(VALUE value, rb_data_type_t* rb_data_type, T* data)
314
+ inline Wrapper<T*>* wrapConstructed(VALUE value, rb_data_type_t* rb_data_type, T* data)
258
315
  {
259
316
  using Wrapper_T = Wrapper<T*>;
260
-
317
+
261
318
  Wrapper_T* wrapper = nullptr;
262
319
  TypedData_Get_Struct(value, Wrapper_T, rb_data_type, wrapper);
263
320
  if (wrapper)
264
321
  {
265
- Registries::instance.instances.remove(wrapper->get());
322
+ Registries::instance.instances.remove(wrapper->get(rb_data_type));
266
323
  delete wrapper;
267
324
  }
268
325
 
269
- wrapper = new Wrapper_T(data, true);
326
+ wrapper = new Wrapper_T(rb_data_type, data, true);
270
327
  RTYPEDDATA_DATA(value) = wrapper;
271
328
 
272
329
  Registries::instance.instances.add(data, value);
330
+
331
+ return wrapper;
273
332
  }
274
- } // namespace
333
+ }
data/rice/rice.hpp CHANGED
@@ -156,6 +156,9 @@
156
156
  // Dependent on Module, Class, Array and String
157
157
  #include "forward_declares.ipp"
158
158
 
159
+ // Dependent on Module, Array, Symbol - used by stl smart pointers
160
+ #include "detail/Forwards.hpp"
161
+
159
162
  // For now include libc support - maybe should be separate header file someday
160
163
  #include "libc/file.hpp"
161
164
 
@@ -17,5 +17,18 @@ inline void Init_Native_Registry()
17
17
  }
18
18
 
19
19
  return result;
20
- }, Arg("klass").setValue());
20
+ }, Arg("klass").setValue()).
21
+
22
+ define_method("lookup_by_kind", [](detail::NativeRegistry& self, VALUE klass, detail::NativeKind kind) -> Array
23
+ {
24
+ Array result;
25
+
26
+ const std::vector<detail::Native*> natives = self.lookup(klass, kind);
27
+ for (detail::Native* native : natives)
28
+ {
29
+ result.push(native, false);
30
+ }
31
+
32
+ return result;
33
+ }, Arg("klass").setValue(), Arg("kind"));
21
34
  }
@@ -13,7 +13,7 @@ namespace Rice::stl
13
13
  define_method("message", &std::exception::what);
14
14
 
15
15
  define_class_under<std::runtime_error>(rb_mStd, "RuntimeError", rb_eRuntimeError).
16
- define_constructor(Constructor<std::runtime_error, const char*>()).
16
+ define_constructor(Constructor<std::runtime_error, const char*>(), Arg("what")).
17
17
  define_method("message", &std::runtime_error::what);
18
18
  }
19
19
  }
@@ -11,7 +11,7 @@ namespace Rice
11
11
 
12
12
  define_class_under<std::filesystem::path>(rb_mFileSystem, "Path").
13
13
  define_constructor(Constructor<std::filesystem::path>()).
14
- define_constructor(Constructor<std::filesystem::path, std::string>());
14
+ define_constructor(Constructor<std::filesystem::path, std::string>(), Arg("source"));
15
15
  }
16
16
  }
17
17
  }
data/rice/stl/map.ipp CHANGED
@@ -14,6 +14,8 @@ namespace Rice
14
14
  using Size_T = typename T::size_type;
15
15
  using Difference_T = typename T::difference_type;
16
16
  using To_Ruby_T = typename detail::remove_cv_recursive_t<Mapped_T>;
17
+ // For pointer types, use the pointer directly; for non-pointer types, use a reference
18
+ using Mapped_Parameter_T = std::conditional_t<std::is_pointer_v<Mapped_T>, Mapped_T, Mapped_T&>;
17
19
 
18
20
  public:
19
21
  MapHelper(Data_Type<T> klass) : klass_(klass)
@@ -42,7 +44,7 @@ namespace Rice
42
44
 
43
45
  if constexpr (std::is_copy_constructible_v<Key_T> && std::is_copy_constructible_v<Value_T>)
44
46
  {
45
- klass_.define_constructor(Constructor<T, const T&>());
47
+ klass_.define_constructor(Constructor<T, const T&>(), Arg("other"));
46
48
  }
47
49
  }
48
50
 
@@ -71,11 +73,11 @@ namespace Rice
71
73
  {
72
74
  return std::nullopt;
73
75
  }
74
- })
76
+ }, Arg("key"))
75
77
  .define_method("include?", [](T& map, Key_T& key) -> bool
76
78
  {
77
79
  return map.find(key) != map.end();
78
- })
80
+ }, Arg("key"))
79
81
  .define_method("keys", [](T& map) -> std::vector<Key_T>
80
82
  {
81
83
  std::vector<Key_T> result;
@@ -110,8 +112,8 @@ namespace Rice
110
112
  klass_.define_method("==", [](T& map, T& other)->bool
111
113
  {
112
114
  return map == other;
113
- })
114
- .define_method("value?", [](T& map, Mapped_T& value) -> bool
115
+ }, Arg("other"))
116
+ .define_method("value?", [](T& map, Mapped_Parameter_T value) -> bool
115
117
  {
116
118
  auto it = std::find_if(map.begin(), map.end(),
117
119
  [&value](auto& pair)
@@ -120,15 +122,15 @@ namespace Rice
120
122
  });
121
123
 
122
124
  return it != map.end();
123
- });
125
+ }, Arg("value"));
124
126
  rb_define_alias(klass_, "eql?", "==");
125
127
  }
126
128
  else
127
129
  {
128
- klass_.define_method("value?", [](T&, Mapped_T&) -> bool
130
+ klass_.define_method("value?", [](T&, Mapped_Parameter_T) -> bool
129
131
  {
130
132
  return false;
131
- });
133
+ }, Arg("value"));
132
134
  }
133
135
 
134
136
  rb_define_alias(klass_, "has_value", "value?");
@@ -151,12 +153,12 @@ namespace Rice
151
153
  {
152
154
  return std::nullopt;
153
155
  }
154
- })
155
- .define_method("[]=", [](T& map, Key_T key, Mapped_T& value) -> Mapped_T
156
+ }, Arg("key"))
157
+ .define_method("[]=", [](T& map, Key_T key, Mapped_Parameter_T value) -> Mapped_T
156
158
  {
157
159
  map[key] = value;
158
160
  return value;
159
- });
161
+ }, Arg("key").keepAlive(), Arg("value").keepAlive());
160
162
 
161
163
  rb_define_alias(klass_, "store", "[]=");
162
164
  }
@@ -14,6 +14,8 @@ namespace Rice
14
14
  using Size_T = typename T::size_type;
15
15
  using Difference_T = typename T::difference_type;
16
16
  using To_Ruby_T = typename detail::remove_cv_recursive_t<Mapped_T>;
17
+ // For pointer types, use the pointer directly; for non-pointer types, use a reference
18
+ using Mapped_Parameter_T = std::conditional_t<std::is_pointer_v<Mapped_T>, Mapped_T, Mapped_T&>;
17
19
 
18
20
  public:
19
21
  MultimapHelper(Data_Type<T> klass) : klass_(klass)
@@ -41,7 +43,7 @@ namespace Rice
41
43
 
42
44
  if constexpr (std::is_copy_constructible_v<Key_T> && std::is_copy_constructible_v<Value_T>)
43
45
  {
44
- klass_.define_constructor(Constructor<T, const T&>());
46
+ klass_.define_constructor(Constructor<T, const T&>(), Arg("other"));
45
47
  }
46
48
  }
47
49
 
@@ -70,11 +72,11 @@ namespace Rice
70
72
  }
71
73
 
72
74
  return result;
73
- })
75
+ }, Arg("key"))
74
76
  .define_method("include?", [](T& multimap, Key_T& key) -> bool
75
77
  {
76
78
  return multimap.find(key) != multimap.end();
77
- })
79
+ }, Arg("key"))
78
80
  .define_method("keys", [](T& multimap) -> std::vector<Key_T>
79
81
  {
80
82
  std::vector<Key_T> result;
@@ -109,8 +111,8 @@ namespace Rice
109
111
  klass_.define_method("==", [](T& multimap, T& other)->bool
110
112
  {
111
113
  return multimap == other;
112
- })
113
- .define_method("value?", [](T& multimap, Mapped_T& value) -> bool
114
+ }, Arg("other"))
115
+ .define_method("value?", [](T& multimap, Mapped_Parameter_T value) -> bool
114
116
  {
115
117
  auto it = std::find_if(multimap.begin(), multimap.end(),
116
118
  [&value](auto& pair)
@@ -119,15 +121,15 @@ namespace Rice
119
121
  });
120
122
 
121
123
  return it != multimap.end();
122
- });
124
+ }, Arg("value"));
123
125
  rb_define_alias(klass_, "eql?", "==");
124
126
  }
125
127
  else
126
128
  {
127
- klass_.define_method("value?", [](T&, Mapped_T&) -> bool
129
+ klass_.define_method("value?", [](T&, Mapped_Parameter_T) -> bool
128
130
  {
129
131
  return false;
130
- });
132
+ }, Arg("value"));
131
133
  }
132
134
 
133
135
  rb_define_alias(klass_, "has_value", "value?");
@@ -150,13 +152,13 @@ namespace Rice
150
152
  {
151
153
  return std::nullopt;
152
154
  }
153
- })
154
- .define_method("insert", [](T& map, Key_T key, Mapped_T& value) -> Mapped_T
155
+ }, Arg("key"))
156
+ .define_method("insert", [](T& map, Key_T key, Mapped_Parameter_T value) -> Mapped_T
155
157
  {
156
158
  Value_T element{ key, value };
157
159
  map.insert(element);
158
160
  return value;
159
- });
161
+ }, Arg("key").keepAlive(), Arg("value").keepAlive());
160
162
  }
161
163
 
162
164
  void define_enumerable()
data/rice/stl/pair.ipp CHANGED
@@ -7,6 +7,12 @@ namespace Rice
7
7
  template<typename T>
8
8
  class PairHelper
9
9
  {
10
+ using First_T = typename T::first_type;
11
+ using Second_T = typename T::second_type;
12
+ // For pointer types, use the pointer directly; for non-pointer types, use a reference
13
+ using First_Parameter_T = std::conditional_t<std::is_pointer_v<First_T>, First_T, First_T&>;
14
+ using Second_Parameter_T = std::conditional_t<std::is_pointer_v<Second_T>, Second_T, Second_T&>;
15
+
10
16
  public:
11
17
  PairHelper(Data_Type<T> klass) : klass_(klass)
12
18
  {
@@ -19,33 +25,33 @@ namespace Rice
19
25
  void define_constructors()
20
26
  {
21
27
  klass_.define_constructor(Constructor<T>())
22
- .define_constructor(Constructor<T, typename T::first_type&, typename T::second_type&>());
23
-
24
- if constexpr (std::is_copy_constructible_v<typename T::first_type> && std::is_copy_constructible_v<typename T::second_type>)
28
+ .define_constructor(Constructor<T, First_Parameter_T, Second_Parameter_T>(), Arg("x").keepAlive(), Arg("y").keepAlive());
29
+
30
+ if constexpr (std::is_copy_constructible_v<First_T> && std::is_copy_constructible_v<Second_T>)
25
31
  {
26
- klass_.define_constructor(Constructor<T, const T&>());
32
+ klass_.define_constructor(Constructor<T, const T&>(), Arg("other"));
27
33
  }
28
34
  }
29
35
 
30
36
  void define_attributes()
31
37
  {
32
38
  // Access methods
33
- if constexpr (std::is_const_v<std::remove_reference_t<std::remove_pointer_t<typename T::first_type>>>)
39
+ if constexpr (std::is_const_v<std::remove_reference_t<std::remove_pointer_t<First_T>>>)
34
40
  {
35
41
  klass_.define_attr("first", &T::first, Rice::AttrAccess::Read);
36
42
  }
37
43
  else
38
44
  {
39
- klass_.define_attr("first", &T::first, Rice::AttrAccess::ReadWrite);
45
+ klass_.define_attr("first", &T::first, Rice::AttrAccess::ReadWrite, Arg("value").keepAlive());
40
46
  }
41
47
 
42
- if constexpr (std::is_const_v<std::remove_reference_t<std::remove_pointer_t<typename T::second_type>>>)
48
+ if constexpr (std::is_const_v<std::remove_reference_t<std::remove_pointer_t<Second_T>>>)
43
49
  {
44
50
  klass_.define_attr("second", &T::second, Rice::AttrAccess::Read);
45
51
  }
46
52
  else
47
53
  {
48
- klass_.define_attr("second", &T::second, Rice::AttrAccess::ReadWrite);
54
+ klass_.define_attr("second", &T::second, Rice::AttrAccess::ReadWrite, Arg("value").keepAlive());
49
55
  }
50
56
  }
51
57
 
data/rice/stl/set.ipp CHANGED
@@ -38,7 +38,7 @@ namespace Rice
38
38
  void define_constructors()
39
39
  {
40
40
  klass_.define_constructor(Constructor<T>())
41
- .define_constructor(Constructor<T, const T&>());
41
+ .define_constructor(Constructor<T, const T&>(), Arg("other"));
42
42
  }
43
43
 
44
44
  void define_capacity_methods()
@@ -58,11 +58,11 @@ namespace Rice
58
58
  {
59
59
  auto iter = self.find(element);
60
60
  return iter != self.end();
61
- })
61
+ }, Arg("key"))
62
62
  .define_method("count", [](T& self, const Key_T element) -> Size_T
63
63
  {
64
64
  return self.count(element);
65
- });
65
+ }, Arg("key"));
66
66
  }
67
67
 
68
68
  void define_modify_methods()
@@ -73,17 +73,17 @@ namespace Rice
73
73
  {
74
74
  self.erase(key);
75
75
  return self;
76
- })
77
- .define_method("insert", [](T& self, const Value_T value) -> T&
76
+ }, Arg("key"))
77
+ .define_method("insert", [](T& self, Parameter_T value) -> T&
78
78
  {
79
79
  self.insert(value);
80
80
  return self;
81
- })
81
+ }, Arg("value").keepAlive())
82
82
  .define_method("merge", [](T& self, T& other) -> T&
83
83
  {
84
84
  self.merge(other);
85
85
  return self;
86
- });
86
+ }, Arg("source"));
87
87
 
88
88
  rb_define_alias(klass_, "erase", "delete");
89
89
  }
@@ -91,11 +91,11 @@ namespace Rice
91
91
  void define_operators()
92
92
  {
93
93
  klass_
94
- .define_method("<<", [](T& self, const Value_T value) -> T&
94
+ .define_method("<<", [](T& self, Parameter_T value) -> T&
95
95
  {
96
96
  self.insert(value);
97
97
  return self;
98
- })
98
+ }, Arg("value").keepAlive())
99
99
  .define_method("==", [](const T& self, const T& other) -> bool
100
100
  {
101
101
  if constexpr (detail::is_comparable_v<Value_T>)
@@ -106,7 +106,7 @@ namespace Rice
106
106
  {
107
107
  return false;
108
108
  }
109
- })
109
+ }, Arg("other"))
110
110
  .define_method("&", [](const T& self, const T& other) -> T
111
111
  {
112
112
  T result;
@@ -115,7 +115,7 @@ namespace Rice
115
115
  std::inserter(result, result.begin()));
116
116
 
117
117
  return result;
118
- })
118
+ }, Arg("other"))
119
119
  .define_method("|", [](const T& self, const T& other) -> T
120
120
  {
121
121
  T result;
@@ -124,7 +124,7 @@ namespace Rice
124
124
  std::inserter(result, result.begin()));
125
125
 
126
126
  return result;
127
- })
127
+ }, Arg("other"))
128
128
  .define_method("-", [](const T& self, const T& other) -> T
129
129
  {
130
130
  T result;
@@ -133,7 +133,7 @@ namespace Rice
133
133
  std::inserter(result, result.begin()));
134
134
 
135
135
  return result;
136
- })
136
+ }, Arg("other"))
137
137
  .define_method("^", [](const T& self, const T& other) -> T
138
138
  {
139
139
  T result;
@@ -142,17 +142,17 @@ namespace Rice
142
142
  std::inserter(result, result.begin()));
143
143
 
144
144
  return result;
145
- })
145
+ }, Arg("other"))
146
146
  .define_method("<", [](const T& self, const T& other) -> bool
147
147
  {
148
148
  return std::includes(other.begin(), other.end(),
149
149
  self.begin(), self.end());
150
- })
150
+ }, Arg("other"))
151
151
  .define_method(">", [](const T& self, const T& other) -> bool
152
152
  {
153
153
  return std::includes(self.begin(), self.end(),
154
154
  other.begin(), other.end());
155
- });
155
+ }, Arg("other"));
156
156
 
157
157
  rb_define_alias(klass_, "eql?", "==");
158
158
  rb_define_alias(klass_, "intersection", "&");