rice 4.9.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 (51) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +17 -1
  3. data/CMakePresets.json +77 -50
  4. data/FindRuby.cmake +1 -1
  5. data/include/rice/rice.hpp +114 -81
  6. data/include/rice/stl.hpp +157 -95
  7. data/lib/rice/doc/config.rb +57 -57
  8. data/lib/rice/doc/cpp_reference.rb +158 -158
  9. data/lib/rice/doc/doxygen.rb +289 -289
  10. data/lib/rice/doc/mkdocs.rb +332 -332
  11. data/lib/rice/doc/rice.rb +48 -48
  12. data/lib/rice/doc/ruby.rb +26 -26
  13. data/lib/rice/native.rb +15 -15
  14. data/lib/rice/native_registry.rb +12 -12
  15. data/lib/rice/parameter.rb +5 -5
  16. data/lib/rice/rbs.rb +71 -71
  17. data/lib/rice/version.rb +1 -1
  18. data/lib/rubygems/builder.rb +9 -9
  19. data/lib/rubygems_plugin.rb +8 -8
  20. data/rice/Data_Type.ipp +1 -1
  21. data/rice/detail/Native.ipp +2 -4
  22. data/rice/detail/NativeAttributeGet.ipp +1 -1
  23. data/rice/detail/NativeAttributeSet.hpp +5 -3
  24. data/rice/detail/NativeAttributeSet.ipp +41 -33
  25. data/rice/detail/NativeMethod.ipp +25 -22
  26. data/rice/detail/NativeRegistry.hpp +3 -2
  27. data/rice/detail/NativeRegistry.ipp +13 -9
  28. data/rice/detail/Parameter.ipp +3 -4
  29. data/rice/detail/Wrapper.hpp +5 -1
  30. data/rice/detail/Wrapper.ipp +15 -1
  31. data/rice/stl/exception.ipp +1 -1
  32. data/rice/stl/filesystem.ipp +1 -1
  33. data/rice/stl/map.ipp +13 -11
  34. data/rice/stl/multimap.ipp +13 -11
  35. data/rice/stl/pair.ipp +14 -8
  36. data/rice/stl/set.ipp +16 -16
  37. data/rice/stl/shared_ptr.ipp +15 -1
  38. data/rice/stl/type_index.ipp +1 -1
  39. data/rice/stl/unique_ptr.ipp +2 -2
  40. data/rice/stl/unordered_map.ipp +14 -12
  41. data/rice/stl/vector.ipp +67 -31
  42. data/test/test_Attribute.cpp +72 -0
  43. data/test/test_Callback.cpp +3 -0
  44. data/test/test_Stl_Map.cpp +46 -0
  45. data/test/test_Stl_Multimap.cpp +46 -0
  46. data/test/test_Stl_Set.cpp +34 -0
  47. data/test/test_Stl_Unordered_Map.cpp +46 -0
  48. data/test/test_Stl_Variant.cpp +10 -14
  49. data/test/test_Stl_Vector.cpp +140 -13
  50. data/test/test_Tracking.cpp +3 -0
  51. metadata +1 -1
@@ -107,30 +107,33 @@ namespace Rice::detail
107
107
  {
108
108
  return self;
109
109
  }
110
- /* This case happens when a class wrapped by Rice is calling a method
111
- defined on an ancestor class. For example, the std::map size method
112
- is defined on _Tree not map. Rice needs to know the actual type
113
- that was wrapped so it can correctly extract the C++ object from
114
- the Ruby object. */
115
- else if constexpr (!std::is_same_v<intrinsic_type<Receiver_T>, Class_T> &&
116
- std::is_base_of_v<intrinsic_type<Receiver_T>, Class_T> &&
117
- std::is_pointer_v<Receiver_T>)
118
- {
119
- Class_T* instance = From_Ruby<Class_T*>().convert(self);
120
- return dynamic_cast<Receiver_T>(instance);
121
- }
122
- else if constexpr (!std::is_same_v<intrinsic_type<Receiver_T>, Class_T> &&
123
- std::is_base_of_v<intrinsic_type<Receiver_T>, Class_T> &&
124
- std::is_reference_v<Receiver_T>)
125
- {
126
- Class_T& instance = From_Ruby<Class_T&>().convert(self);
127
- return dynamic_cast<Receiver_T>(instance);
128
- }
129
- // Self parameter could be derived from Object or it is an C++ instance and
130
- // needs to be unwrapped from Ruby
131
110
  else
132
111
  {
133
- return From_Ruby<Receiver_T>().convert(self);
112
+ /* When a class wrapped by Rice calls a method defined on an ancestor class
113
+ (e.g., std::map calling a method from _Tree), we need to unwrap as Class_T
114
+ and dynamic_cast to the base class. Otherwise unwrap directly as Receiver_T. */
115
+ constexpr bool isDerived = !std::is_same_v<intrinsic_type<Receiver_T>, Class_T> &&
116
+ std::is_base_of_v<intrinsic_type<Receiver_T>, Class_T>;
117
+
118
+ if constexpr (isDerived)
119
+ {
120
+ if constexpr (std::is_pointer_v<Receiver_T>)
121
+ {
122
+ Class_T* instance = From_Ruby<Class_T*>().convert(self);
123
+ return dynamic_cast<Receiver_T>(instance);
124
+ }
125
+ else if constexpr (std::is_reference_v<Receiver_T>)
126
+ {
127
+ Class_T& instance = From_Ruby<Class_T&>().convert(self);
128
+ return dynamic_cast<Receiver_T>(instance);
129
+ }
130
+ }
131
+ else
132
+ {
133
+ // Note GCC has a false warning: function may return address of local variable [-Wreturn-local-addr].
134
+ // From_Ruby returns a reference to data in the Ruby object, not the temporary.
135
+ return From_Ruby<Receiver_T>().convert(self);
136
+ }
134
137
  }
135
138
  }
136
139
 
@@ -31,10 +31,11 @@ namespace Rice::detail
31
31
  NativeRegistry& operator=(const NativeRegistry& other) = delete;
32
32
 
33
33
  void add(VALUE klass, ID methodId, std::unique_ptr<Native>& native);
34
+ void replace(VALUE klass, ID methodId, std::unique_ptr<Native>& native);
34
35
  void reset(VALUE klass);
35
36
 
36
- const std::vector<Native*> lookup(VALUE klass);
37
- const std::vector<std::unique_ptr<Native>>& lookup(VALUE klass, ID methodId);
37
+ std::vector<Native*> lookup(VALUE klass);
38
+ std::vector<std::unique_ptr<Native>>& lookup(VALUE klass, ID methodId);
38
39
  std::vector<Native*> lookup(VALUE klass, NativeKind kind);
39
40
 
40
41
  private:
@@ -3,17 +3,21 @@ namespace Rice::detail
3
3
  {
4
4
  inline void NativeRegistry::add(VALUE klass, ID methodId, std::unique_ptr<Native>& native)
5
5
  {
6
- if (rb_type(klass) == T_ICLASS)
7
- {
8
- klass = detail::protect(rb_class_of, klass);
9
- }
6
+ // Lookup items for method
7
+ std::vector<std::unique_ptr<Native>>& natives = NativeRegistry::lookup(klass, methodId);
10
8
 
11
- // Create the key
12
- std::pair<VALUE, ID> key = std::make_pair(klass, methodId);
9
+ // Add new native
10
+ natives.push_back(std::move(native));
11
+ }
13
12
 
13
+ inline void NativeRegistry::replace(VALUE klass, ID methodId, std::unique_ptr<Native>& native)
14
+ {
14
15
  // Lookup items for method
15
- std::vector<std::unique_ptr<Native>>& natives = this->natives_[key];
16
+ std::vector<std::unique_ptr<Native>>& natives = NativeRegistry::lookup(klass, methodId);
16
17
 
18
+ // Clear existing natives
19
+ natives.clear();
20
+ // Add new native
17
21
  natives.push_back(std::move(native));
18
22
  }
19
23
 
@@ -33,7 +37,7 @@ namespace Rice::detail
33
37
  }
34
38
  }
35
39
 
36
- inline const std::vector<Native*> NativeRegistry::lookup(VALUE klass)
40
+ inline std::vector<Native*> NativeRegistry::lookup(VALUE klass)
37
41
  {
38
42
  std::vector<Native*> result;
39
43
 
@@ -59,7 +63,7 @@ namespace Rice::detail
59
63
  return result;
60
64
  }
61
65
 
62
- inline const std::vector<std::unique_ptr<Native>>& NativeRegistry::lookup(VALUE klass, ID methodId)
66
+ inline std::vector<std::unique_ptr<Native>>& NativeRegistry::lookup(VALUE klass, ID methodId)
63
67
  {
64
68
  if (rb_type(klass) == T_ICLASS)
65
69
  {
@@ -43,17 +43,16 @@ namespace Rice::detail
43
43
  // One caveat - procs are also RUBY_T_DATA so don't check if this is a function type
44
44
  if (result == Convertible::Exact && rb_type(value) == RUBY_T_DATA && !std::is_function_v<std::remove_pointer_t<T>>)
45
45
  {
46
- // Check the constness of the Ruby wrapped value and the parameter
47
- WrapperBase* wrapper = getWrapper(value);
46
+ bool isConst = WrapperBase::isConst(value);
48
47
 
49
48
  // Do not send a const value to a non-const parameter
50
- if (wrapper->isConst() && !is_const_any_v<T>)
49
+ if (isConst && !is_const_any_v<T>)
51
50
  {
52
51
  result = Convertible::None;
53
52
  }
54
53
  // It is ok to send a non-const value to a const parameter but
55
54
  // prefer non-const to non-const by slightly decreasing the score
56
- else if (!wrapper->isConst() && is_const_any_v<T>)
55
+ else if (!isConst && is_const_any_v<T>)
57
56
  {
58
57
  result = Convertible::ConstMismatch;
59
58
  }
@@ -5,6 +5,10 @@ namespace Rice::detail
5
5
  {
6
6
  class WrapperBase
7
7
  {
8
+ public:
9
+ static void addKeepAlive(VALUE object, VALUE keepAlive);
10
+ static bool isConst(VALUE object);
11
+
8
12
  public:
9
13
  WrapperBase(rb_data_type_t* rb_data_type);
10
14
  virtual ~WrapperBase() = default;
@@ -78,7 +82,7 @@ namespace Rice::detail
78
82
 
79
83
  // ---- Helper Functions ---------
80
84
  template <typename T>
81
- void wrapConstructed(VALUE value, rb_data_type_t* rb_data_type, T* data);
85
+ Wrapper<T*>* wrapConstructed(VALUE value, rb_data_type_t* rb_data_type, T* data);
82
86
 
83
87
  template <typename T>
84
88
  VALUE wrap(VALUE klass, rb_data_type_t* rb_data_type, T& data, bool isOwner);
@@ -2,6 +2,18 @@
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
+
5
17
  inline WrapperBase::WrapperBase(rb_data_type_t* rb_data_type) : rb_data_type_(rb_data_type)
6
18
  {
7
19
  }
@@ -299,7 +311,7 @@ namespace Rice::detail
299
311
  }
300
312
 
301
313
  template <typename T>
302
- 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)
303
315
  {
304
316
  using Wrapper_T = Wrapper<T*>;
305
317
 
@@ -315,5 +327,7 @@ namespace Rice::detail
315
327
  RTYPEDDATA_DATA(value) = wrapper;
316
328
 
317
329
  Registries::instance.instances.add(data, value);
330
+
331
+ return wrapper;
318
332
  }
319
333
  }
@@ -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", "&");
@@ -23,7 +23,7 @@ namespace Rice
23
23
  Identifier id(klassName);
24
24
  Data_Type_T result = define_class_under<detail::intrinsic_type<SharedPtr_T>>(rb_mStd, id).
25
25
  define_method("get", &SharedPtr_T::get).
26
- define_method("swap", &SharedPtr_T::swap).
26
+ define_method("swap", &SharedPtr_T::swap, Arg("r")).
27
27
  define_method("use_count", &SharedPtr_T::use_count).
28
28
  define_method("empty?", [](SharedPtr_T& self)->bool
29
29
  {
@@ -115,4 +115,18 @@ namespace Rice::detail
115
115
  return result;
116
116
  }
117
117
  };
118
+
119
+ #ifdef __GLIBCXX__
120
+ // libstdc++ implementation detail: std::shared_ptr inherits from
121
+ // std::__shared_ptr<T, _Lock_policy>. Methods like swap() expose this
122
+ // internal type through their parameter signatures.
123
+ template<typename T, __gnu_cxx::_Lock_policy Policy>
124
+ struct Type<std::__shared_ptr<T, Policy>>
125
+ {
126
+ static bool verify()
127
+ {
128
+ return true;
129
+ }
130
+ };
131
+ #endif
118
132
  }
@@ -6,7 +6,7 @@ namespace Rice::stl
6
6
  {
7
7
  Module rb_mStd = define_module("Std");
8
8
  return define_class_under<std::type_index>(rb_mStd, "TypeIndex").
9
- define_constructor(Constructor<std::type_index, const std::type_info&>()).
9
+ define_constructor(Constructor<std::type_index, const std::type_info&>(), Arg("target")).
10
10
  define_method("hash_code", &std::type_index::hash_code).
11
11
  define_method("name", &std::type_index::name);
12
12
  }
@@ -24,8 +24,8 @@ namespace Rice
24
24
  Data_Type_T result = define_class_under<detail::intrinsic_type<UniquePtr_T>>(rb_mStd, id).
25
25
  define_method("get", &UniquePtr_T::get).
26
26
  define_method("release", &UniquePtr_T::release).
27
- define_method("reset", &UniquePtr_T::reset).
28
- define_method("swap", &UniquePtr_T::swap).
27
+ define_method("reset", &UniquePtr_T::reset, Arg("ptr")).
28
+ define_method("swap", &UniquePtr_T::swap, Arg("other")).
29
29
  define_method("empty?", [](UniquePtr_T& self)->bool
30
30
  {
31
31
  return !self;