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.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +26 -0
  3. data/CMakePresets.json +3 -3
  4. data/bin/rice-doc.rb +2 -0
  5. data/include/rice/rice.hpp +162 -113
  6. data/include/rice/stl.hpp +229 -69
  7. data/lib/mkmf-rice.rb +2 -2
  8. data/lib/rice/version.rb +1 -1
  9. data/rice/Constructor.ipp +3 -3
  10. data/rice/Data_Object.ipp +0 -42
  11. data/rice/JumpException.ipp +1 -0
  12. data/rice/Reference.hpp +2 -2
  13. data/rice/Reference.ipp +1 -1
  14. data/rice/cpp_api/Encoding.ipp +0 -48
  15. data/rice/cpp_api/Hash.ipp +19 -0
  16. data/rice/cpp_api/Object.hpp +2 -2
  17. data/rice/cpp_api/Object.ipp +3 -3
  18. data/rice/cpp_api/String.ipp +19 -0
  19. data/rice/detail/Anchor.hpp +1 -1
  20. data/rice/detail/Anchor.ipp +16 -10
  21. data/rice/detail/Parameter.ipp +11 -0
  22. data/rice/detail/Proc.ipp +19 -0
  23. data/rice/detail/Wrapper.ipp +3 -3
  24. data/rice/detail/from_ruby.hpp +1 -0
  25. data/rice/detail/to_ruby.ipp +58 -1
  26. data/rice/stl/function.ipp +142 -2
  27. data/rice/stl/map.ipp +2 -10
  28. data/rice/stl/multimap.ipp +2 -10
  29. data/rice/stl/optional.ipp +18 -0
  30. data/rice/stl/reference_wrapper.ipp +18 -0
  31. data/rice/stl/set.ipp +24 -25
  32. data/rice/stl/unique_ptr.ipp +3 -0
  33. data/rice/stl/unordered_map.ipp +2 -10
  34. data/rice/stl/vector.ipp +18 -15
  35. data/rice/traits/rice_traits.hpp +3 -0
  36. data/test/test_Attribute.cpp +6 -6
  37. data/test/test_Constructor.cpp +140 -1
  38. data/test/test_File.cpp +2 -3
  39. data/test/test_From_Ruby.cpp +3 -3
  40. data/test/test_Hash.cpp +8 -0
  41. data/test/test_Object.cpp +76 -0
  42. data/test/test_Overloads.cpp +74 -1
  43. data/test/test_Proc.cpp +11 -1
  44. data/test/test_Reference.cpp +20 -1
  45. data/test/test_Stl_Exception.cpp +2 -5
  46. data/test/test_Stl_Function.cpp +72 -7
  47. data/test/test_Stl_Map.cpp +10 -1
  48. data/test/test_Stl_Multimap.cpp +11 -2
  49. data/test/test_Stl_Optional.cpp +9 -0
  50. data/test/test_Stl_Reference_Wrapper.cpp +11 -0
  51. data/test/test_Stl_Set.cpp +12 -0
  52. data/test/test_Stl_Unordered_Map.cpp +10 -1
  53. data/test/test_Stl_Vector.cpp +130 -11
  54. data/test/test_String.cpp +7 -0
  55. data/test/test_To_Ruby.cpp +24 -1
  56. metadata +1 -1
@@ -2,23 +2,28 @@ namespace Rice
2
2
  {
3
3
  namespace detail
4
4
  {
5
- inline Anchor::Anchor(VALUE value) : 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
- detail::protect(rb_gc_unregister_address, &this->value_);
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
- detail::protect(rb_set_end_proc, &Anchor::disable, Qnil);
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
  }
@@ -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...)>
@@ -121,10 +121,10 @@ namespace Rice::detail
121
121
 
122
122
  if constexpr (is_complete_v<T>)
123
123
  {
124
- // is_abstract_v requires a complete type, so nest inside is_complete_v.
125
- // Deleting an abstract class through a non-virtual destructor is UB,
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::is_abstract_v<T> || std::has_virtual_destructor_v<T>))
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
  {
@@ -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
 
@@ -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
+ }
@@ -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... args)
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
+ }
@@ -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
+ }
@@ -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
- .define_method("<<", [](T& self, Parameter_T value) -> T&
106
- {
107
- self.insert(value);
108
- return self;
109
- }, Arg("value").keepAlive())
110
- .define_method("==", [](const T& self, const T& other) -> bool
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
- if constexpr (detail::is_comparable_v<Value_T>)
113
- {
114
- return self == other;
115
- }
116
- else
117
- {
118
- return false;
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
- rb_define_alias(klass_, "eql?", "==");
169
- rb_define_alias(klass_, "intersection", "&");
170
- rb_define_alias(klass_, "union", "|");
171
- rb_define_alias(klass_, "difference", "-");
172
- rb_define_alias(klass_, "proper_subset?", "<");
173
- rb_define_alias(klass_, "subset?", "<");
174
- rb_define_alias(klass_, "proper_superset?", ">");
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()
@@ -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
 
@@ -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
  }
@@ -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
 
@@ -306,13 +306,13 @@ TESTCASE(not_assignable)
306
306
  //);
307
307
 
308
308
  c.define_attr("not_assignable", &DataStruct::notAssignable, AttrAccess::Read);
309
- Data_Object<NotAssignable> notAssignable = notAssignableClass.call("new");
309
+ Object notAssignable = notAssignableClass.call("new");
310
310
 
311
- Data_Object<DataStruct> o = c.call("new");
311
+ Object dataStruct = c.call("new");
312
312
 
313
313
  ASSERT_EXCEPTION_CHECK(
314
314
  Exception,
315
- o.call("not_assignable=", notAssignable),
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
- Data_Object<NotCopyable> notCopyable = notCopyableClass.call("new");
336
+ Object notCopyable = notCopyableClass.call("new");
337
337
 
338
- Data_Object<DataStruct> o = c.call("new");
338
+ Object dataStruct = c.call("new");
339
339
 
340
340
  ASSERT_EXCEPTION_CHECK(
341
341
  Exception,
342
- o.call("not_assignable=", notCopyable),
342
+ dataStruct.call("not_assignable=", notCopyable),
343
343
  ASSERT_MATCH(R"(undefined method (`|')not_assignable=')", ex.what())
344
344
  );
345
345
  }