rice 4.7.1 → 4.8.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 (153) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +29 -1
  3. data/CMakeLists.txt +14 -22
  4. data/CMakePresets.json +203 -75
  5. data/FindRuby.cmake +358 -123
  6. data/bin/rice-doc.rb +56 -141
  7. data/include/rice/api.hpp +248 -0
  8. data/include/rice/rice.hpp +2237 -1657
  9. data/include/rice/stl.hpp +346 -443
  10. data/lib/rice/doc/config.rb +70 -0
  11. data/lib/rice/doc/cpp_reference.rb +1 -4
  12. data/lib/rice/doc/mkdocs.rb +58 -20
  13. data/lib/rice/doc/rice.rb +20 -0
  14. data/lib/rice/doc.rb +1 -0
  15. data/lib/rice/make_rice_headers.rb +7 -0
  16. data/lib/rice/native_registry.rb +2 -2
  17. data/lib/rice/rbs.rb +2 -2
  18. data/lib/rice/version.rb +1 -1
  19. data/lib/rubygems_plugin.rb +12 -9
  20. data/rice/Arg.hpp +12 -6
  21. data/rice/Arg.ipp +14 -7
  22. data/rice/Buffer.ipp +44 -40
  23. data/rice/Callback.hpp +1 -1
  24. data/rice/Callback.ipp +2 -7
  25. data/rice/Constructor.hpp +1 -1
  26. data/rice/Constructor.ipp +11 -11
  27. data/rice/Data_Object.ipp +15 -15
  28. data/rice/Data_Type.hpp +9 -10
  29. data/rice/Data_Type.ipp +22 -25
  30. data/rice/Director.hpp +1 -0
  31. data/rice/Enum.ipp +58 -39
  32. data/rice/Exception.hpp +4 -4
  33. data/rice/Exception.ipp +7 -7
  34. data/rice/NoGVL.hpp +13 -0
  35. data/rice/Reference.hpp +56 -0
  36. data/rice/Reference.ipp +96 -0
  37. data/rice/Return.hpp +4 -1
  38. data/rice/Return.ipp +0 -6
  39. data/rice/cpp_api/Array.hpp +41 -4
  40. data/rice/cpp_api/Array.ipp +105 -9
  41. data/rice/cpp_api/Class.hpp +2 -2
  42. data/rice/cpp_api/Class.ipp +4 -4
  43. data/rice/cpp_api/Hash.ipp +7 -4
  44. data/rice/cpp_api/Module.hpp +4 -4
  45. data/rice/cpp_api/Module.ipp +12 -10
  46. data/rice/cpp_api/Object.hpp +4 -4
  47. data/rice/cpp_api/Object.ipp +15 -12
  48. data/rice/cpp_api/String.hpp +2 -2
  49. data/rice/cpp_api/String.ipp +11 -8
  50. data/rice/cpp_api/Symbol.ipp +7 -7
  51. data/rice/cpp_api/shared_methods.hpp +5 -9
  52. data/rice/detail/InstanceRegistry.hpp +0 -2
  53. data/rice/detail/Native.hpp +31 -21
  54. data/rice/detail/Native.ipp +282 -130
  55. data/rice/detail/NativeAttributeGet.hpp +5 -7
  56. data/rice/detail/NativeAttributeGet.ipp +26 -26
  57. data/rice/detail/NativeAttributeSet.hpp +2 -4
  58. data/rice/detail/NativeAttributeSet.ipp +20 -16
  59. data/rice/detail/NativeCallback.hpp +77 -0
  60. data/rice/detail/NativeCallback.ipp +280 -0
  61. data/rice/detail/NativeFunction.hpp +11 -21
  62. data/rice/detail/NativeFunction.ipp +58 -119
  63. data/rice/detail/NativeInvoker.hpp +4 -4
  64. data/rice/detail/NativeInvoker.ipp +7 -7
  65. data/rice/detail/NativeIterator.hpp +2 -4
  66. data/rice/detail/NativeIterator.ipp +18 -14
  67. data/rice/detail/NativeMethod.hpp +10 -20
  68. data/rice/detail/NativeMethod.ipp +54 -114
  69. data/rice/detail/NativeProc.hpp +5 -7
  70. data/rice/detail/NativeProc.ipp +39 -28
  71. data/rice/detail/NativeRegistry.hpp +0 -1
  72. data/rice/detail/Parameter.hpp +15 -8
  73. data/rice/detail/Parameter.ipp +102 -43
  74. data/rice/detail/Proc.ipp +14 -28
  75. data/rice/detail/RubyType.ipp +2 -53
  76. data/rice/detail/Type.hpp +23 -7
  77. data/rice/detail/Type.ipp +73 -93
  78. data/rice/detail/TypeRegistry.ipp +5 -4
  79. data/rice/detail/Wrapper.hpp +1 -1
  80. data/rice/detail/Wrapper.ipp +18 -10
  81. data/rice/detail/from_ruby.hpp +8 -6
  82. data/rice/detail/from_ruby.ipp +306 -173
  83. data/rice/detail/ruby.hpp +23 -0
  84. data/rice/libc/file.hpp +4 -4
  85. data/rice/rice.hpp +6 -8
  86. data/rice/rice_api/Native.ipp +5 -1
  87. data/rice/rice_api/Parameter.ipp +1 -1
  88. data/rice/ruby_mark.hpp +2 -1
  89. data/rice/stl/complex.ipp +12 -8
  90. data/rice/stl/map.ipp +27 -22
  91. data/rice/stl/monostate.ipp +16 -12
  92. data/rice/stl/multimap.hpp +0 -2
  93. data/rice/stl/multimap.ipp +27 -22
  94. data/rice/stl/optional.ipp +27 -11
  95. data/rice/stl/pair.ipp +5 -5
  96. data/rice/stl/reference_wrapper.ipp +5 -4
  97. data/rice/stl/set.ipp +16 -16
  98. data/rice/stl/shared_ptr.hpp +0 -16
  99. data/rice/stl/shared_ptr.ipp +34 -190
  100. data/rice/stl/string.ipp +18 -18
  101. data/rice/stl/string_view.ipp +1 -1
  102. data/rice/stl/tuple.ipp +15 -36
  103. data/rice/stl/unique_ptr.ipp +18 -8
  104. data/rice/stl/unordered_map.ipp +20 -15
  105. data/rice/stl/variant.ipp +37 -21
  106. data/rice/stl/vector.ipp +41 -36
  107. data/rice/traits/function_traits.hpp +19 -19
  108. data/rice/traits/method_traits.hpp +4 -4
  109. data/rice/traits/rice_traits.hpp +162 -39
  110. data/rice.gemspec +1 -3
  111. data/test/test_Array.cpp +261 -3
  112. data/test/test_Attribute.cpp +6 -3
  113. data/test/test_Buffer.cpp +6 -42
  114. data/test/test_Callback.cpp +77 -23
  115. data/test/test_Data_Object.cpp +1 -1
  116. data/test/test_Data_Type.cpp +21 -22
  117. data/test/test_Director.cpp +2 -4
  118. data/test/test_Enum.cpp +34 -5
  119. data/test/test_File.cpp +9 -5
  120. data/test/test_From_Ruby.cpp +4 -3
  121. data/test/test_GVL.cpp +3 -3
  122. data/test/test_Hash.cpp +1 -1
  123. data/test/test_Iterator.cpp +54 -22
  124. data/test/test_Keep_Alive.cpp +1 -1
  125. data/test/test_Keep_Alive_No_Wrapper.cpp +1 -1
  126. data/test/test_Module.cpp +5 -5
  127. data/test/test_Overloads.cpp +345 -48
  128. data/test/test_Proc.cpp +54 -0
  129. data/test/test_Reference.cpp +181 -0
  130. data/test/test_Self.cpp +2 -2
  131. data/test/test_Stl_Set.cpp +6 -6
  132. data/test/test_Stl_SharedPtr.cpp +54 -30
  133. data/test/test_Stl_String_View.cpp +4 -2
  134. data/test/test_Stl_Tuple.cpp +1 -1
  135. data/test/test_Stl_Variant.cpp +6 -14
  136. data/test/test_Stl_Vector.cpp +61 -30
  137. data/test/test_String.cpp +4 -2
  138. data/test/test_Struct.cpp +1 -1
  139. data/test/test_Symbol.cpp +1 -1
  140. data/test/test_To_Ruby.cpp +1 -0
  141. data/test/test_Type.cpp +36 -35
  142. data/test/test_global_functions.cpp +1 -1
  143. data/test/unittest.cpp +1 -1
  144. data/test/unittest.hpp +5 -5
  145. metadata +10 -10
  146. data/rice/Function.hpp +0 -17
  147. data/rice/Function.ipp +0 -13
  148. data/rice/detail/MethodInfo.hpp +0 -48
  149. data/rice/detail/MethodInfo.ipp +0 -99
  150. data/rice/detail/NativeCallbackFFI.hpp +0 -55
  151. data/rice/detail/NativeCallbackFFI.ipp +0 -152
  152. data/rice/detail/NativeCallbackSimple.hpp +0 -30
  153. data/rice/detail/NativeCallbackSimple.ipp +0 -29
data/rice/detail/Type.ipp CHANGED
@@ -71,37 +71,20 @@ namespace Rice::detail
71
71
  {
72
72
  };
73
73
 
74
- // ---------- TypeMapper ------------
75
- template<typename T>
76
- inline std::string TypeMapper<T>::demangle(char const* mangled_name)
74
+ // ---------- TypeIndexParser ------------
75
+ inline TypeIndexParser::TypeIndexParser(const std::type_index& typeIndex, bool isFundamental) :
76
+ typeIndex_(typeIndex), isFundamental_(isFundamental)
77
77
  {
78
- #ifdef __GNUC__
79
- struct Helper
80
- {
81
- Helper(
82
- char const* mangled_name)
83
- : name_(0)
84
- {
85
- int status = 0;
86
- name_ = abi::__cxa_demangle(mangled_name, 0, 0, &status);
87
- }
88
-
89
- ~Helper()
90
- {
91
- std::free(name_);
92
- }
93
-
94
- char* name_;
95
-
96
- private:
97
- Helper(Helper const&);
98
- void operator=(Helper const&);
99
- };
78
+ }
100
79
 
101
- Helper helper(mangled_name);
102
- if (helper.name_)
80
+ inline std::string TypeIndexParser::demangle(char const* mangled_name)
81
+ {
82
+ #ifdef __GNUC__
83
+ int status = 0;
84
+ char* name = abi::__cxa_demangle(mangled_name, 0, 0, &status);
85
+ if (name)
103
86
  {
104
- return helper.name_;
87
+ return name;
105
88
  }
106
89
  else
107
90
  {
@@ -112,17 +95,9 @@ namespace Rice::detail
112
95
  #endif
113
96
  }
114
97
 
115
- template<typename T>
116
- inline std::string TypeMapper<T>::name()
98
+ inline std::string TypeIndexParser::name()
117
99
  {
118
- const std::type_index& typeIndex = typeid(T);
119
- return demangle(typeIndex.name());
120
- }
121
-
122
- template<typename T>
123
- inline std::string TypeMapper<T>::name(const std::type_index& typeIndex)
124
- {
125
- return demangle(typeIndex.name());
100
+ return this->demangle(this->typeIndex_.name());
126
101
  }
127
102
 
128
103
  // Find text inside of < > taking into account nested groups.
@@ -130,8 +105,7 @@ namespace Rice::detail
130
105
  // Example:
131
106
  //
132
107
  // std::vector<std::vector<int>, std::allocator<std::vector, std::allocator<int>>>
133
- template<typename T>
134
- inline std::string TypeMapper<T>::findGroup(std::string& string, size_t offset)
108
+ inline std::string TypeIndexParser::findGroup(std::string& string, size_t offset)
135
109
  {
136
110
  int depth = 0;
137
111
 
@@ -164,8 +138,7 @@ namespace Rice::detail
164
138
  throw std::runtime_error("Unbalanced Group");
165
139
  }
166
140
 
167
- template<typename T>
168
- inline void TypeMapper<T>::replaceAll(std::string& string, std::regex regex, std::string replacement)
141
+ inline void TypeIndexParser::replaceAll(std::string& string, std::regex regex, std::string replacement)
169
142
  {
170
143
  std::smatch match;
171
144
  while (std::regex_search(string, match, regex))
@@ -174,8 +147,7 @@ namespace Rice::detail
174
147
  }
175
148
  }
176
149
 
177
- template<typename T>
178
- inline void TypeMapper<T>::removeGroup(std::string& string, std::regex regex)
150
+ inline void TypeIndexParser::removeGroup(std::string& string, std::regex regex)
179
151
  {
180
152
  std::smatch match;
181
153
  while (std::regex_search(string, match, regex))
@@ -186,8 +158,7 @@ namespace Rice::detail
186
158
  }
187
159
  }
188
160
 
189
- template<typename T>
190
- inline void TypeMapper<T>::replaceGroup(std::string& string, std::regex regex, std::string replacement)
161
+ inline void TypeIndexParser::replaceGroup(std::string& string, std::regex regex, std::string replacement)
191
162
  {
192
163
  std::smatch match;
193
164
  while (std::regex_search(string, match, regex))
@@ -198,8 +169,7 @@ namespace Rice::detail
198
169
  }
199
170
  }
200
171
 
201
- template<typename T>
202
- inline std::string TypeMapper<T>::simplifiedName()
172
+ inline std::string TypeIndexParser::simplifiedName()
203
173
  {
204
174
  std::string base = this->name();
205
175
 
@@ -271,42 +241,9 @@ namespace Rice::detail
271
241
  return base;
272
242
  }
273
243
 
274
- template<typename T>
275
- inline void TypeMapper<T>::capitalizeHelper(std::string& content, std::regex& regex)
276
- {
277
- std::smatch match;
278
- while (std::regex_search(content, match, regex))
279
- {
280
- std::string replacement = match[1];
281
- std::transform(replacement.begin(), replacement.end(), replacement.begin(), ::toupper);
282
- content.replace(match.position(), match.length(), replacement);
283
- }
284
- }
285
-
286
- template<typename T>
287
- inline std::string TypeMapper<T>::rubyTypeName()
288
- {
289
- using Intrinsic_T = detail::intrinsic_type<T>;
290
-
291
- if constexpr (std::is_fundamental_v<T>)
292
- {
293
- return RubyType<Intrinsic_T>::name;
294
- }
295
- else if constexpr (std::is_same_v<std::remove_cv_t<T>, char*>)
296
- {
297
- return "String";
298
- }
299
- else
300
- {
301
- detail::TypeMapper<Intrinsic_T> typeIntrinsicMapper;
302
- return typeIntrinsicMapper.simplifiedName();
303
- }
304
- }
305
-
306
- template<typename T>
307
- inline std::string TypeMapper<T>::rubyName()
244
+ inline std::string TypeIndexParser::rubyName(std::string rubyTypeName)
308
245
  {
309
- std::string base = this->rubyTypeName();
246
+ std::string base = rubyTypeName;
310
247
 
311
248
  // Remove std:: these could be embedded in template types
312
249
  auto stdRegex = std::regex("std::");
@@ -318,50 +255,93 @@ namespace Rice::detail
318
255
  base = std::regex_replace(base, leadingNamespacesRegex, "");
319
256
 
320
257
  // Capitalize first letter
321
- base[0] = std::toupper(base[0]);
258
+ base[0] = (char)std::toupper(base[0]);
322
259
 
323
260
  // Replace :: with unicode U+u02F8 (Modified Letter raised colon)
324
261
  auto colonRegex = std::regex(R"(:)");
325
- replaceAll(base, colonRegex, "\uA789");
262
+ this->replaceAll(base, colonRegex, "\uA789");
326
263
 
327
264
  // Replace _ and capitalize the next letter
328
265
  std::regex underscoreRegex(R"(_(\w))");
329
- capitalizeHelper(base, underscoreRegex);
266
+ this->capitalizeHelper(base, underscoreRegex);
330
267
 
331
- if constexpr (std::is_fundamental_v<intrinsic_type<T>>)
268
+ if (this->isFundamental_)
332
269
  {
333
270
  // Replace space and capitalize the next letter
334
271
  std::regex spaceRegex(R"(\s+(\w))");
335
- capitalizeHelper(base, spaceRegex);
272
+ this->capitalizeHelper(base, spaceRegex);
336
273
  }
337
274
  else
338
275
  {
339
276
  // Replace spaces with unicode U+u00A0 (Non breaking Space)
340
277
  std::regex spaceRegex = std::regex(R"(\s+)");
341
- replaceAll(base, spaceRegex, "\u00A0");
278
+ this->replaceAll(base, spaceRegex, "\u00A0");
342
279
  }
343
280
 
344
281
  // Replace < with unicode U+227A (Precedes)
345
282
  auto lessThanRegex = std::regex("<");
346
283
  //replaceAll(base, lessThanRegex, "≺");
347
- replaceAll(base, lessThanRegex, "\u227A");
284
+ this->replaceAll(base, lessThanRegex, "\u227A");
348
285
 
349
286
  // Replace > with unicode U+227B (Succeeds)
350
287
  auto greaterThanRegex = std::regex(">");
351
288
  //replaceAll(base, greaterThanRegex, "≻");
352
- replaceAll(base, greaterThanRegex, "\u227B");
289
+ this->replaceAll(base, greaterThanRegex, "\u227B");
353
290
 
354
291
  // Replace , with Unicode Character (U+066C) - Arabic Thousands Separator
355
292
  auto commaRegex = std::regex(R"(,\s*)");
356
- replaceAll(base, commaRegex, "\u201A");
293
+ this->replaceAll(base, commaRegex, "\u201A");
357
294
 
358
295
  // Replace * with Unicode Character (U+2217) - Asterisk Operator
359
296
  auto asteriskRegex = std::regex(R"(\*)");
360
- replaceAll(base, asteriskRegex, "\u2217");
297
+ this->replaceAll(base, asteriskRegex, "\u2217");
361
298
 
362
299
  return base;
363
300
  }
364
301
 
302
+ inline void TypeIndexParser::capitalizeHelper(std::string& content, std::regex& regex)
303
+ {
304
+ std::smatch match;
305
+ while (std::regex_search(content, match, regex))
306
+ {
307
+ std::string replacement = match[1];
308
+ std::transform(replacement.begin(), replacement.end(), replacement.begin(),
309
+ [](unsigned char c) -> char
310
+ {
311
+ return static_cast<char>(std::toupper(c));
312
+ });
313
+ content.replace(match.position(), match.length(), replacement);
314
+ }
315
+ }
316
+
317
+ // ---------- TypeMapper ------------
318
+ template<typename T>
319
+ inline std::string TypeMapper<T>::rubyTypeName()
320
+ {
321
+ using Intrinsic_T = detail::intrinsic_type<T>;
322
+
323
+ if constexpr (std::is_fundamental_v<T>)
324
+ {
325
+ return RubyType<Intrinsic_T>::name;
326
+ }
327
+ else if constexpr (std::is_same_v<std::remove_cv_t<T>, char*>)
328
+ {
329
+ return "String";
330
+ }
331
+ else
332
+ {
333
+ detail::TypeIndexParser typeIndexParser(typeid(Intrinsic_T), std::is_fundamental_v<detail::intrinsic_type<Intrinsic_T>>);
334
+ return typeIndexParser.simplifiedName();
335
+ }
336
+ }
337
+
338
+ template<typename T>
339
+ inline std::string TypeMapper<T>::rubyName()
340
+ {
341
+ std::string base = this->rubyTypeName();
342
+ return this->typeIndexParser_.rubyName(base);
343
+ }
344
+
365
345
  template<typename T>
366
346
  inline VALUE TypeMapper<T>::rubyKlass()
367
347
  {
@@ -97,8 +97,9 @@ namespace Rice::detail
97
97
  return result.value();
98
98
  }
99
99
 
100
- detail::TypeMapper<T> typeMapper;
101
- raiseUnverifiedType(typeMapper.name());
100
+ detail::TypeIndexParser typeIndexParser(typeid(T), std::is_fundamental_v<detail::intrinsic_type<T>>);
101
+ raiseUnverifiedType(typeIndexParser.name());
102
+
102
103
  // Make the compiler happy
103
104
  return std::pair<VALUE, rb_data_type_t*>(Qnil, nullptr);
104
105
  }
@@ -131,8 +132,8 @@ namespace Rice::detail
131
132
 
132
133
  for (const std::type_index& typeIndex : this->unverified_)
133
134
  {
134
- detail::TypeMapper<int> typeMapper;
135
- stream << " " << typeMapper.name(typeIndex) << "\n";
135
+ detail::TypeIndexParser typeIndexParser(typeIndex);
136
+ stream << " " << typeIndexParser.name() << "\n";
136
137
  }
137
138
 
138
139
  throw std::invalid_argument(stream.str());
@@ -77,7 +77,7 @@ namespace Rice::detail
77
77
 
78
78
  // ---- Helper Functions ---------
79
79
  template <typename T>
80
- void wrapConstructed(VALUE value, rb_data_type_t* rb_data_type, T* data, bool isOwner);
80
+ void wrapConstructed(VALUE value, rb_data_type_t* rb_data_type, T* data);
81
81
 
82
82
  template <typename T>
83
83
  VALUE wrap(VALUE klass, rb_data_type_t* rb_data_type, T& data, bool isOwner);
@@ -29,6 +29,7 @@ namespace Rice::detail
29
29
  template <typename T>
30
30
  inline Wrapper<T>::Wrapper(T& data): data_(data)
31
31
  {
32
+ this->isConst_ = std::is_const_v<std::remove_reference_t<T>>;
32
33
  }
33
34
 
34
35
  template <typename T>
@@ -139,7 +140,7 @@ namespace Rice::detail
139
140
  result = TypedData_Wrap_Struct(klass, rb_data_type, wrapper);
140
141
  }
141
142
 
142
- // std::is_copy_constructible_v<std::vector<std::unique_ptr<T>>>> return true. Sigh.
143
+ // std::is_copy_constructible_v<std::vector<std::unique_ptr<T>>>> returns true. Sigh.
143
144
  else if constexpr (detail::is_std_vector_v<T>)
144
145
  {
145
146
  if constexpr (std::is_copy_constructible_v<typename T::value_type>)
@@ -170,9 +171,9 @@ namespace Rice::detail
170
171
 
171
172
  else
172
173
  {
173
- detail::TypeMapper<T> typeMapper;
174
+ detail::TypeIndexParser typeIndexParser(typeid(T), std::is_fundamental_v<detail::intrinsic_type<T>>);
174
175
  std::string message = "Rice was directed to take ownership of a C++ object but it does not have an accessible copy or move constructor. Type: " +
175
- typeMapper.name();
176
+ typeIndexParser.name();
176
177
  throw std::runtime_error(message);
177
178
  }
178
179
 
@@ -201,7 +202,8 @@ namespace Rice::detail
201
202
  {
202
203
  if (rb_type(value) != RUBY_T_DATA)
203
204
  {
204
- std::string message = "The provided Ruby object does not wrap a C++ object";
205
+ std::string message = "The Ruby object does not wrap a C++ object. It is actually a " +
206
+ std::string(detail::protect(rb_obj_classname, value)) + ".";
205
207
  throw std::runtime_error(message);
206
208
  }
207
209
 
@@ -233,12 +235,18 @@ namespace Rice::detail
233
235
  inline WrapperBase* getWrapper(VALUE value)
234
236
  {
235
237
  // Turn off spurious warning on g++ 12
236
- #if defined(__GNUC__) || defined(__clang__)
237
- #pragma GCC diagnostic push
238
- #pragma GCC diagnostic ignored "-Warray-bounds"
239
- #endif
238
+ #if defined(__GNUC__) || defined(__clang__)
239
+ #pragma GCC diagnostic push
240
+ #pragma GCC diagnostic ignored "-Warray-bounds"
241
+ #endif
242
+
243
+ if (!RTYPEDDATA_P(value))
244
+ {
245
+ throw Exception(rb_eTypeError, "wrong argument type %s (expected %s)",
246
+ detail::protect(rb_obj_classname, value), "wrapped C++ object");
247
+ }
240
248
 
241
- return RTYPEDDATA_P(value) ? static_cast<WrapperBase*>(RTYPEDDATA_DATA(value)) : nullptr;
249
+ return static_cast<WrapperBase*>(RTYPEDDATA_DATA(value));
242
250
 
243
251
  #if defined(__GNUC__) || defined(__clang__)
244
252
  #pragma GCC diagnostic pop
@@ -246,7 +254,7 @@ namespace Rice::detail
246
254
  }
247
255
 
248
256
  template <typename T>
249
- inline void wrapConstructed(VALUE value, rb_data_type_t* rb_data_type, T* data, bool isOwner)
257
+ inline void wrapConstructed(VALUE value, rb_data_type_t* rb_data_type, T* data)
250
258
  {
251
259
  using Wrapper_T = Wrapper<T*>;
252
260
 
@@ -30,13 +30,15 @@ namespace Rice::detail
30
30
  template <typename T>
31
31
  class From_Ruby;
32
32
 
33
- enum class Convertible: uint8_t
33
+ // Overload resolution scoring constants
34
+ struct Convertible
34
35
  {
35
- None = 0b0000,
36
- Narrow = 0b0001,
37
- Cast = 0b0011,
38
- Const = 0b0111,
39
- Exact = 0b1111
36
+ static constexpr double Exact = 1.0; // Perfect type match
37
+ static constexpr double None = 0.0; // Cannot convert
38
+ static constexpr double IntToFloat = 0.5; // Domain change penalty when converting int to float
39
+ static constexpr double SignedToUnsigned = 0.5;// Penalty for signed to unsigned (can't represent negatives)
40
+ static constexpr double FloatToInt = 0.5; // Domain change penalty when converting float to int (lossy)
41
+ static constexpr double ConstMismatch = 0.99; // Penalty for const mismatch
40
42
  };
41
43
  }
42
44