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
data/include/rice/stl.hpp CHANGED
@@ -53,7 +53,7 @@ namespace Rice::stl
53
53
  define_method("message", &std::exception::what);
54
54
 
55
55
  define_class_under<std::runtime_error>(rb_mStd, "RuntimeError", rb_eRuntimeError).
56
- define_constructor(Constructor<std::runtime_error, const char*>()).
56
+ define_constructor(Constructor<std::runtime_error, const char*>(), Arg("what")).
57
57
  define_method("message", &std::runtime_error::what);
58
58
  }
59
59
  }
@@ -694,7 +694,7 @@ namespace Rice
694
694
 
695
695
  define_class_under<std::filesystem::path>(rb_mFileSystem, "Path").
696
696
  define_constructor(Constructor<std::filesystem::path>()).
697
- define_constructor(Constructor<std::filesystem::path, std::string>());
697
+ define_constructor(Constructor<std::filesystem::path, std::string>(), Arg("source"));
698
698
  }
699
699
  }
700
700
  }
@@ -990,6 +990,12 @@ namespace Rice
990
990
  template<typename T>
991
991
  class PairHelper
992
992
  {
993
+ using First_T = typename T::first_type;
994
+ using Second_T = typename T::second_type;
995
+ // For pointer types, use the pointer directly; for non-pointer types, use a reference
996
+ using First_Parameter_T = std::conditional_t<std::is_pointer_v<First_T>, First_T, First_T&>;
997
+ using Second_Parameter_T = std::conditional_t<std::is_pointer_v<Second_T>, Second_T, Second_T&>;
998
+
993
999
  public:
994
1000
  PairHelper(Data_Type<T> klass) : klass_(klass)
995
1001
  {
@@ -1002,33 +1008,33 @@ namespace Rice
1002
1008
  void define_constructors()
1003
1009
  {
1004
1010
  klass_.define_constructor(Constructor<T>())
1005
- .define_constructor(Constructor<T, typename T::first_type&, typename T::second_type&>());
1006
-
1007
- if constexpr (std::is_copy_constructible_v<typename T::first_type> && std::is_copy_constructible_v<typename T::second_type>)
1011
+ .define_constructor(Constructor<T, First_Parameter_T, Second_Parameter_T>(), Arg("x").keepAlive(), Arg("y").keepAlive());
1012
+
1013
+ if constexpr (std::is_copy_constructible_v<First_T> && std::is_copy_constructible_v<Second_T>)
1008
1014
  {
1009
- klass_.define_constructor(Constructor<T, const T&>());
1015
+ klass_.define_constructor(Constructor<T, const T&>(), Arg("other"));
1010
1016
  }
1011
1017
  }
1012
1018
 
1013
1019
  void define_attributes()
1014
1020
  {
1015
1021
  // Access methods
1016
- if constexpr (std::is_const_v<std::remove_reference_t<std::remove_pointer_t<typename T::first_type>>>)
1022
+ if constexpr (std::is_const_v<std::remove_reference_t<std::remove_pointer_t<First_T>>>)
1017
1023
  {
1018
1024
  klass_.define_attr("first", &T::first, Rice::AttrAccess::Read);
1019
1025
  }
1020
1026
  else
1021
1027
  {
1022
- klass_.define_attr("first", &T::first, Rice::AttrAccess::ReadWrite);
1028
+ klass_.define_attr("first", &T::first, Rice::AttrAccess::ReadWrite, Arg("value").keepAlive());
1023
1029
  }
1024
1030
 
1025
- if constexpr (std::is_const_v<std::remove_reference_t<std::remove_pointer_t<typename T::second_type>>>)
1031
+ if constexpr (std::is_const_v<std::remove_reference_t<std::remove_pointer_t<Second_T>>>)
1026
1032
  {
1027
1033
  klass_.define_attr("second", &T::second, Rice::AttrAccess::Read);
1028
1034
  }
1029
1035
  else
1030
1036
  {
1031
- klass_.define_attr("second", &T::second, Rice::AttrAccess::ReadWrite);
1037
+ klass_.define_attr("second", &T::second, Rice::AttrAccess::ReadWrite, Arg("value").keepAlive());
1032
1038
  }
1033
1039
  }
1034
1040
 
@@ -1130,6 +1136,8 @@ namespace Rice
1130
1136
  using Size_T = typename T::size_type;
1131
1137
  using Difference_T = typename T::difference_type;
1132
1138
  using To_Ruby_T = typename detail::remove_cv_recursive_t<Mapped_T>;
1139
+ // For pointer types, use the pointer directly; for non-pointer types, use a reference
1140
+ using Mapped_Parameter_T = std::conditional_t<std::is_pointer_v<Mapped_T>, Mapped_T, Mapped_T&>;
1133
1141
 
1134
1142
  public:
1135
1143
  MapHelper(Data_Type<T> klass) : klass_(klass)
@@ -1158,7 +1166,7 @@ namespace Rice
1158
1166
 
1159
1167
  if constexpr (std::is_copy_constructible_v<Key_T> && std::is_copy_constructible_v<Value_T>)
1160
1168
  {
1161
- klass_.define_constructor(Constructor<T, const T&>());
1169
+ klass_.define_constructor(Constructor<T, const T&>(), Arg("other"));
1162
1170
  }
1163
1171
  }
1164
1172
 
@@ -1187,11 +1195,11 @@ namespace Rice
1187
1195
  {
1188
1196
  return std::nullopt;
1189
1197
  }
1190
- })
1198
+ }, Arg("key"))
1191
1199
  .define_method("include?", [](T& map, Key_T& key) -> bool
1192
1200
  {
1193
1201
  return map.find(key) != map.end();
1194
- })
1202
+ }, Arg("key"))
1195
1203
  .define_method("keys", [](T& map) -> std::vector<Key_T>
1196
1204
  {
1197
1205
  std::vector<Key_T> result;
@@ -1226,8 +1234,8 @@ namespace Rice
1226
1234
  klass_.define_method("==", [](T& map, T& other)->bool
1227
1235
  {
1228
1236
  return map == other;
1229
- })
1230
- .define_method("value?", [](T& map, Mapped_T& value) -> bool
1237
+ }, Arg("other"))
1238
+ .define_method("value?", [](T& map, Mapped_Parameter_T value) -> bool
1231
1239
  {
1232
1240
  auto it = std::find_if(map.begin(), map.end(),
1233
1241
  [&value](auto& pair)
@@ -1236,15 +1244,15 @@ namespace Rice
1236
1244
  });
1237
1245
 
1238
1246
  return it != map.end();
1239
- });
1247
+ }, Arg("value"));
1240
1248
  rb_define_alias(klass_, "eql?", "==");
1241
1249
  }
1242
1250
  else
1243
1251
  {
1244
- klass_.define_method("value?", [](T&, Mapped_T&) -> bool
1252
+ klass_.define_method("value?", [](T&, Mapped_Parameter_T) -> bool
1245
1253
  {
1246
1254
  return false;
1247
- });
1255
+ }, Arg("value"));
1248
1256
  }
1249
1257
 
1250
1258
  rb_define_alias(klass_, "has_value", "value?");
@@ -1267,12 +1275,12 @@ namespace Rice
1267
1275
  {
1268
1276
  return std::nullopt;
1269
1277
  }
1270
- })
1271
- .define_method("[]=", [](T& map, Key_T key, Mapped_T& value) -> Mapped_T
1278
+ }, Arg("key"))
1279
+ .define_method("[]=", [](T& map, Key_T key, Mapped_Parameter_T value) -> Mapped_T
1272
1280
  {
1273
1281
  map[key] = value;
1274
1282
  return value;
1275
- });
1283
+ }, Arg("key").keepAlive(), Arg("value").keepAlive());
1276
1284
 
1277
1285
  rb_define_alias(klass_, "store", "[]=");
1278
1286
  }
@@ -1733,6 +1741,8 @@ namespace Rice
1733
1741
  using Size_T = typename T::size_type;
1734
1742
  using Difference_T = typename T::difference_type;
1735
1743
  using To_Ruby_T = typename detail::remove_cv_recursive_t<Mapped_T>;
1744
+ // For pointer types, use the pointer directly; for non-pointer types, use a reference
1745
+ using Mapped_Parameter_T = std::conditional_t<std::is_pointer_v<Mapped_T>, Mapped_T, Mapped_T&>;
1736
1746
 
1737
1747
  public:
1738
1748
  MultimapHelper(Data_Type<T> klass) : klass_(klass)
@@ -1760,7 +1770,7 @@ namespace Rice
1760
1770
 
1761
1771
  if constexpr (std::is_copy_constructible_v<Key_T> && std::is_copy_constructible_v<Value_T>)
1762
1772
  {
1763
- klass_.define_constructor(Constructor<T, const T&>());
1773
+ klass_.define_constructor(Constructor<T, const T&>(), Arg("other"));
1764
1774
  }
1765
1775
  }
1766
1776
 
@@ -1789,11 +1799,11 @@ namespace Rice
1789
1799
  }
1790
1800
 
1791
1801
  return result;
1792
- })
1802
+ }, Arg("key"))
1793
1803
  .define_method("include?", [](T& multimap, Key_T& key) -> bool
1794
1804
  {
1795
1805
  return multimap.find(key) != multimap.end();
1796
- })
1806
+ }, Arg("key"))
1797
1807
  .define_method("keys", [](T& multimap) -> std::vector<Key_T>
1798
1808
  {
1799
1809
  std::vector<Key_T> result;
@@ -1828,8 +1838,8 @@ namespace Rice
1828
1838
  klass_.define_method("==", [](T& multimap, T& other)->bool
1829
1839
  {
1830
1840
  return multimap == other;
1831
- })
1832
- .define_method("value?", [](T& multimap, Mapped_T& value) -> bool
1841
+ }, Arg("other"))
1842
+ .define_method("value?", [](T& multimap, Mapped_Parameter_T value) -> bool
1833
1843
  {
1834
1844
  auto it = std::find_if(multimap.begin(), multimap.end(),
1835
1845
  [&value](auto& pair)
@@ -1838,15 +1848,15 @@ namespace Rice
1838
1848
  });
1839
1849
 
1840
1850
  return it != multimap.end();
1841
- });
1851
+ }, Arg("value"));
1842
1852
  rb_define_alias(klass_, "eql?", "==");
1843
1853
  }
1844
1854
  else
1845
1855
  {
1846
- klass_.define_method("value?", [](T&, Mapped_T&) -> bool
1856
+ klass_.define_method("value?", [](T&, Mapped_Parameter_T) -> bool
1847
1857
  {
1848
1858
  return false;
1849
- });
1859
+ }, Arg("value"));
1850
1860
  }
1851
1861
 
1852
1862
  rb_define_alias(klass_, "has_value", "value?");
@@ -1869,13 +1879,13 @@ namespace Rice
1869
1879
  {
1870
1880
  return std::nullopt;
1871
1881
  }
1872
- })
1873
- .define_method("insert", [](T& map, Key_T key, Mapped_T& value) -> Mapped_T
1882
+ }, Arg("key"))
1883
+ .define_method("insert", [](T& map, Key_T key, Mapped_Parameter_T value) -> Mapped_T
1874
1884
  {
1875
1885
  Value_T element{ key, value };
1876
1886
  map.insert(element);
1877
1887
  return value;
1878
- });
1888
+ }, Arg("key").keepAlive(), Arg("value").keepAlive());
1879
1889
  }
1880
1890
 
1881
1891
  void define_enumerable()
@@ -2214,7 +2224,7 @@ namespace Rice
2214
2224
  void define_constructors()
2215
2225
  {
2216
2226
  klass_.define_constructor(Constructor<T>())
2217
- .define_constructor(Constructor<T, const T&>());
2227
+ .define_constructor(Constructor<T, const T&>(), Arg("other"));
2218
2228
  }
2219
2229
 
2220
2230
  void define_capacity_methods()
@@ -2234,11 +2244,11 @@ namespace Rice
2234
2244
  {
2235
2245
  auto iter = self.find(element);
2236
2246
  return iter != self.end();
2237
- })
2247
+ }, Arg("key"))
2238
2248
  .define_method("count", [](T& self, const Key_T element) -> Size_T
2239
2249
  {
2240
2250
  return self.count(element);
2241
- });
2251
+ }, Arg("key"));
2242
2252
  }
2243
2253
 
2244
2254
  void define_modify_methods()
@@ -2249,17 +2259,17 @@ namespace Rice
2249
2259
  {
2250
2260
  self.erase(key);
2251
2261
  return self;
2252
- })
2253
- .define_method("insert", [](T& self, const Value_T value) -> T&
2262
+ }, Arg("key"))
2263
+ .define_method("insert", [](T& self, Parameter_T value) -> T&
2254
2264
  {
2255
2265
  self.insert(value);
2256
2266
  return self;
2257
- })
2267
+ }, Arg("value").keepAlive())
2258
2268
  .define_method("merge", [](T& self, T& other) -> T&
2259
2269
  {
2260
2270
  self.merge(other);
2261
2271
  return self;
2262
- });
2272
+ }, Arg("source"));
2263
2273
 
2264
2274
  rb_define_alias(klass_, "erase", "delete");
2265
2275
  }
@@ -2267,11 +2277,11 @@ namespace Rice
2267
2277
  void define_operators()
2268
2278
  {
2269
2279
  klass_
2270
- .define_method("<<", [](T& self, const Value_T value) -> T&
2280
+ .define_method("<<", [](T& self, Parameter_T value) -> T&
2271
2281
  {
2272
2282
  self.insert(value);
2273
2283
  return self;
2274
- })
2284
+ }, Arg("value").keepAlive())
2275
2285
  .define_method("==", [](const T& self, const T& other) -> bool
2276
2286
  {
2277
2287
  if constexpr (detail::is_comparable_v<Value_T>)
@@ -2282,7 +2292,7 @@ namespace Rice
2282
2292
  {
2283
2293
  return false;
2284
2294
  }
2285
- })
2295
+ }, Arg("other"))
2286
2296
  .define_method("&", [](const T& self, const T& other) -> T
2287
2297
  {
2288
2298
  T result;
@@ -2291,7 +2301,7 @@ namespace Rice
2291
2301
  std::inserter(result, result.begin()));
2292
2302
 
2293
2303
  return result;
2294
- })
2304
+ }, Arg("other"))
2295
2305
  .define_method("|", [](const T& self, const T& other) -> T
2296
2306
  {
2297
2307
  T result;
@@ -2300,7 +2310,7 @@ namespace Rice
2300
2310
  std::inserter(result, result.begin()));
2301
2311
 
2302
2312
  return result;
2303
- })
2313
+ }, Arg("other"))
2304
2314
  .define_method("-", [](const T& self, const T& other) -> T
2305
2315
  {
2306
2316
  T result;
@@ -2309,7 +2319,7 @@ namespace Rice
2309
2319
  std::inserter(result, result.begin()));
2310
2320
 
2311
2321
  return result;
2312
- })
2322
+ }, Arg("other"))
2313
2323
  .define_method("^", [](const T& self, const T& other) -> T
2314
2324
  {
2315
2325
  T result;
@@ -2318,17 +2328,17 @@ namespace Rice
2318
2328
  std::inserter(result, result.begin()));
2319
2329
 
2320
2330
  return result;
2321
- })
2331
+ }, Arg("other"))
2322
2332
  .define_method("<", [](const T& self, const T& other) -> bool
2323
2333
  {
2324
2334
  return std::includes(other.begin(), other.end(),
2325
2335
  self.begin(), self.end());
2326
- })
2336
+ }, Arg("other"))
2327
2337
  .define_method(">", [](const T& self, const T& other) -> bool
2328
2338
  {
2329
2339
  return std::includes(self.begin(), self.end(),
2330
2340
  other.begin(), other.end());
2331
- });
2341
+ }, Arg("other"));
2332
2342
 
2333
2343
  rb_define_alias(klass_, "eql?", "==");
2334
2344
  rb_define_alias(klass_, "intersection", "&");
@@ -2730,7 +2740,7 @@ namespace Rice
2730
2740
  Identifier id(klassName);
2731
2741
  Data_Type_T result = define_class_under<detail::intrinsic_type<SharedPtr_T>>(rb_mStd, id).
2732
2742
  define_method("get", &SharedPtr_T::get).
2733
- define_method("swap", &SharedPtr_T::swap).
2743
+ define_method("swap", &SharedPtr_T::swap, Arg("r")).
2734
2744
  define_method("use_count", &SharedPtr_T::use_count).
2735
2745
  define_method("empty?", [](SharedPtr_T& self)->bool
2736
2746
  {
@@ -2822,6 +2832,20 @@ namespace Rice::detail
2822
2832
  return result;
2823
2833
  }
2824
2834
  };
2835
+
2836
+ #ifdef __GLIBCXX__
2837
+ // libstdc++ implementation detail: std::shared_ptr inherits from
2838
+ // std::__shared_ptr<T, _Lock_policy>. Methods like swap() expose this
2839
+ // internal type through their parameter signatures.
2840
+ template<typename T, __gnu_cxx::_Lock_policy Policy>
2841
+ struct Type<std::__shared_ptr<T, Policy>>
2842
+ {
2843
+ static bool verify()
2844
+ {
2845
+ return true;
2846
+ }
2847
+ };
2848
+ #endif
2825
2849
  }
2826
2850
 
2827
2851
 
@@ -2979,7 +3003,7 @@ namespace Rice::stl
2979
3003
  {
2980
3004
  Module rb_mStd = define_module("Std");
2981
3005
  return define_class_under<std::type_index>(rb_mStd, "TypeIndex").
2982
- define_constructor(Constructor<std::type_index, const std::type_info&>()).
3006
+ define_constructor(Constructor<std::type_index, const std::type_info&>(), Arg("target")).
2983
3007
  define_method("hash_code", &std::type_index::hash_code).
2984
3008
  define_method("name", &std::type_index::name);
2985
3009
  }
@@ -3390,8 +3414,8 @@ namespace Rice
3390
3414
  Data_Type_T result = define_class_under<detail::intrinsic_type<UniquePtr_T>>(rb_mStd, id).
3391
3415
  define_method("get", &UniquePtr_T::get).
3392
3416
  define_method("release", &UniquePtr_T::release).
3393
- define_method("reset", &UniquePtr_T::reset).
3394
- define_method("swap", &UniquePtr_T::swap).
3417
+ define_method("reset", &UniquePtr_T::reset, Arg("ptr")).
3418
+ define_method("swap", &UniquePtr_T::swap, Arg("other")).
3395
3419
  define_method("empty?", [](UniquePtr_T& self)->bool
3396
3420
  {
3397
3421
  return !self;
@@ -3541,6 +3565,8 @@ namespace Rice
3541
3565
  using Size_T = typename T::size_type;
3542
3566
  using Difference_T = typename T::difference_type;
3543
3567
  using To_Ruby_T = typename detail::remove_cv_recursive_t<Mapped_T>;
3568
+ // For pointer types, use the pointer directly; for non-pointer types, use a reference
3569
+ using Mapped_Parameter_T = std::conditional_t<std::is_pointer_v<Mapped_T>, Mapped_T, Mapped_T&>;
3544
3570
 
3545
3571
  public:
3546
3572
  UnorderedMapHelper(Data_Type<T> klass) : klass_(klass)
@@ -3560,7 +3586,7 @@ namespace Rice
3560
3586
 
3561
3587
  void register_pair()
3562
3588
  {
3563
- define_pair<const Key_T, T>();
3589
+ define_pair<const Key_T, Mapped_T>();
3564
3590
  }
3565
3591
 
3566
3592
  void define_constructors()
@@ -3569,7 +3595,7 @@ namespace Rice
3569
3595
 
3570
3596
  if constexpr (std::is_copy_constructible_v<Key_T> && std::is_copy_constructible_v<Value_T>)
3571
3597
  {
3572
- klass_.define_constructor(Constructor<T, const T&>());
3598
+ klass_.define_constructor(Constructor<T, const T&>(), Arg("other"));
3573
3599
  }
3574
3600
  }
3575
3601
 
@@ -3598,11 +3624,11 @@ namespace Rice
3598
3624
  {
3599
3625
  return std::nullopt;
3600
3626
  }
3601
- })
3627
+ }, Arg("key"))
3602
3628
  .define_method("include?", [](T& unordered_map, Key_T& key) -> bool
3603
3629
  {
3604
3630
  return unordered_map.find(key) != unordered_map.end();
3605
- })
3631
+ }, Arg("key"))
3606
3632
  .define_method("keys", [](T& unordered_map) -> std::vector<Key_T>
3607
3633
  {
3608
3634
  std::vector<Key_T> result;
@@ -3637,8 +3663,8 @@ namespace Rice
3637
3663
  klass_.define_method("==", [](T& unordered_map, T& other)->bool
3638
3664
  {
3639
3665
  return unordered_map == other;
3640
- })
3641
- .define_method("value?", [](T& unordered_map, Mapped_T& value) -> bool
3666
+ }, Arg("other"))
3667
+ .define_method("value?", [](T& unordered_map, Mapped_Parameter_T value) -> bool
3642
3668
  {
3643
3669
  auto it = std::find_if(unordered_map.begin(), unordered_map.end(),
3644
3670
  [&value](auto& pair)
@@ -3647,15 +3673,15 @@ namespace Rice
3647
3673
  });
3648
3674
 
3649
3675
  return it != unordered_map.end();
3650
- });
3676
+ }, Arg("value"));
3651
3677
  rb_define_alias(klass_, "eql?", "==");
3652
3678
  }
3653
3679
  else
3654
3680
  {
3655
- klass_.define_method("value?", [](T&, Mapped_T&) -> bool
3681
+ klass_.define_method("value?", [](T&, Mapped_Parameter_T) -> bool
3656
3682
  {
3657
3683
  return false;
3658
- });
3684
+ }, Arg("value"));
3659
3685
  }
3660
3686
 
3661
3687
  rb_define_alias(klass_, "has_value", "value?");
@@ -3678,12 +3704,12 @@ namespace Rice
3678
3704
  {
3679
3705
  return std::nullopt;
3680
3706
  }
3681
- })
3682
- .define_method("[]=", [](T& unordered_map, Key_T key, Mapped_T& value) -> Mapped_T
3707
+ }, Arg("key"))
3708
+ .define_method("[]=", [](T& unordered_map, Key_T key, Mapped_Parameter_T value) -> Mapped_T
3683
3709
  {
3684
3710
  unordered_map[key] = value;
3685
3711
  return value;
3686
- });
3712
+ }, Arg("key").keepAlive(), Arg("value").keepAlive());
3687
3713
 
3688
3714
  rb_define_alias(klass_, "store", "[]=");
3689
3715
  }
@@ -4062,13 +4088,13 @@ namespace Rice
4062
4088
 
4063
4089
  if constexpr (std::is_copy_constructible_v<Value_T>)
4064
4090
  {
4065
- klass_.define_constructor(Constructor<T, const T&>())
4066
- .define_constructor(Constructor<T, Size_T, const Parameter_T>());
4091
+ klass_.define_constructor(Constructor<T, const T&>(), Arg("other"))
4092
+ .define_constructor(Constructor<T, Size_T, const Parameter_T>(), Arg("count"), Arg("value"));
4067
4093
  }
4068
4094
 
4069
4095
  if constexpr (std::is_default_constructible_v<Value_T>)
4070
4096
  {
4071
- klass_.define_constructor(Constructor<T, Size_T>());
4097
+ klass_.define_constructor(Constructor<T, Size_T>(), Arg("count"));
4072
4098
  }
4073
4099
 
4074
4100
  // Allow creation of a vector from a Ruby Array
@@ -4076,18 +4102,20 @@ namespace Rice
4076
4102
  {
4077
4103
  // Create a new vector from the array
4078
4104
  T* data = new T();
4079
- data->reserve(array.size());
4080
4105
 
4106
+ // Wrap the vector
4107
+ detail::Wrapper<T*>* wrapper = detail::wrapConstructed<T>(self, Data_Type<T>::ruby_data_type(), data);
4108
+
4109
+ // Now populate the vector
4081
4110
  detail::From_Ruby<Value_T> fromRuby;
4111
+ data->reserve(array.size());
4082
4112
 
4083
4113
  for (long i = 0; i < array.size(); i++)
4084
4114
  {
4085
4115
  VALUE element = detail::protect(rb_ary_entry, array, i);
4086
4116
  data->push_back(fromRuby.convert(element));
4117
+ wrapper->addKeepAlive(element);
4087
4118
  }
4088
-
4089
- // Wrap the vector
4090
- detail::wrapConstructed<T>(self, Data_Type<T>::ruby_data_type(), data);
4091
4119
  });
4092
4120
  }
4093
4121
 
@@ -4095,18 +4123,18 @@ namespace Rice
4095
4123
  {
4096
4124
  if constexpr (std::is_default_constructible_v<Value_T> && std::is_same_v<Value_T, bool>)
4097
4125
  {
4098
- klass_.define_method("resize", static_cast<void (T::*)(const size_t, bool)>(&T::resize));
4126
+ klass_.define_method("resize", static_cast<void (T::*)(const size_t, bool)>(&T::resize), Arg("count"), Arg("value"));
4099
4127
  }
4100
4128
  else if constexpr (std::is_default_constructible_v<Value_T>)
4101
4129
  {
4102
- klass_.define_method("resize", static_cast<void (T::*)(const size_t)>(&T::resize));
4130
+ klass_.define_method("resize", static_cast<void (T::*)(const size_t)>(&T::resize), Arg("count"));
4103
4131
  }
4104
4132
  else
4105
4133
  {
4106
4134
  klass_.define_method("resize", [](const T&, Size_T)
4107
4135
  {
4108
4136
  // Do nothing
4109
- });
4137
+ }, Arg("count"));
4110
4138
  }
4111
4139
  }
4112
4140
 
@@ -4115,13 +4143,11 @@ namespace Rice
4115
4143
  klass_.define_method("empty?", &T::empty)
4116
4144
  .define_method("capacity", &T::capacity)
4117
4145
  .define_method("max_size", &T::max_size)
4118
- .define_method("reserve", &T::reserve)
4146
+ .define_method("reserve", &T::reserve, Arg("new_cap"))
4119
4147
  .define_method("size", &T::size);
4120
-
4148
+
4121
4149
  rb_define_alias(klass_, "count", "size");
4122
4150
  rb_define_alias(klass_, "length", "size");
4123
- //detail::protect(rb_define_alias, klass_, "count", "size");
4124
- //detail::protect(rb_define_alias, klass_, "length", "size");
4125
4151
  }
4126
4152
 
4127
4153
  void define_access_methods()
@@ -4162,7 +4188,7 @@ namespace Rice
4162
4188
  {
4163
4189
  return vector[index];
4164
4190
  }
4165
- })
4191
+ }, Arg("pos"))
4166
4192
  .template define_method<Value_T*(T::*)()>("data", &T::data, ReturnBuffer());
4167
4193
  }
4168
4194
  else
@@ -4201,7 +4227,7 @@ namespace Rice
4201
4227
  {
4202
4228
  return vector[index];
4203
4229
  }
4204
- });
4230
+ }, Arg("pos"));
4205
4231
  }
4206
4232
 
4207
4233
  klass_.define_method("[]", [this](T& vector, Difference_T start, Difference_T length) -> VALUE
@@ -4234,7 +4260,7 @@ namespace Rice
4234
4260
 
4235
4261
  return result;
4236
4262
  }
4237
- }, Return().setValue());
4263
+ }, Arg("start"), Arg("length"), Return().setValue());
4238
4264
 
4239
4265
  rb_define_alias(klass_, "at", "[]");
4240
4266
  }
@@ -4247,7 +4273,7 @@ namespace Rice
4247
4273
  klass_.define_method("==", [](T& vector, T& other)->bool
4248
4274
  {
4249
4275
  return vector == other;
4250
- })
4276
+ }, Arg("other"))
4251
4277
  .define_method("delete", [](T& vector, Parameter_T element) -> std::optional<Value_T>
4252
4278
  {
4253
4279
  auto iter = std::find(vector.begin(), vector.end(), element);
@@ -4265,11 +4291,11 @@ namespace Rice
4265
4291
  {
4266
4292
  return std::nullopt;
4267
4293
  }
4268
- })
4294
+ }, Arg("value"))
4269
4295
  .define_method("include?", [](T& vector, Parameter_T element)
4270
4296
  {
4271
4297
  return std::find(vector.begin(), vector.end(), element) != vector.end();
4272
- })
4298
+ }, Arg("value"))
4273
4299
  .define_method("index", [](T& vector, Parameter_T element) -> std::optional<Difference_T>
4274
4300
  {
4275
4301
  auto iter = std::find(vector.begin(), vector.end(), element);
@@ -4281,7 +4307,7 @@ namespace Rice
4281
4307
  {
4282
4308
  return iter - vector.begin();
4283
4309
  }
4284
- });
4310
+ }, Arg("value"));
4285
4311
  rb_define_alias(klass_, "eql?", "==");
4286
4312
  }
4287
4313
  else
@@ -4289,15 +4315,15 @@ namespace Rice
4289
4315
  klass_.define_method("delete", [](T&, Parameter_T) -> std::optional<Value_T>
4290
4316
  {
4291
4317
  return std::nullopt;
4292
- })
4318
+ }, Arg("value"))
4293
4319
  .define_method("include?", [](const T&, Parameter_T)
4294
4320
  {
4295
4321
  return false;
4296
- })
4322
+ }, Arg("value"))
4297
4323
  .define_method("index", [](const T&, Parameter_T) -> std::optional<Difference_T>
4298
4324
  {
4299
4325
  return std::nullopt;
4300
- });
4326
+ }, Arg("value"));
4301
4327
  }
4302
4328
  }
4303
4329
 
@@ -4319,7 +4345,7 @@ namespace Rice
4319
4345
  vector.erase(iter);
4320
4346
  return std::nullopt;
4321
4347
  }
4322
- })
4348
+ }, Arg("pos"))
4323
4349
  .define_method("insert", [this](T& vector, Difference_T index, Parameter_T element) -> T&
4324
4350
  {
4325
4351
  size_t normalized = normalizeIndex(vector.size(), index, true);
@@ -4333,7 +4359,7 @@ namespace Rice
4333
4359
  auto iter = vector.begin() + normalized;
4334
4360
  vector.insert(iter, std::move(element));
4335
4361
  return vector;
4336
- })
4362
+ }, Arg("pos"), Arg("value").keepAlive())
4337
4363
  .define_method("pop", [](T& vector) -> std::optional<Value_T>
4338
4364
  {
4339
4365
  if constexpr (!std::is_copy_assignable_v<Value_T>)
@@ -4356,13 +4382,13 @@ namespace Rice
4356
4382
  {
4357
4383
  vector.push_back(std::move(element));
4358
4384
  return vector;
4359
- })
4385
+ }, Arg("value").keepAlive())
4360
4386
  .define_method("shrink_to_fit", &T::shrink_to_fit)
4361
4387
  .define_method("[]=", [this](T& vector, Difference_T index, Parameter_T element) -> void
4362
4388
  {
4363
4389
  index = normalizeIndex(vector.size(), index, true);
4364
4390
  vector[index] = std::move(element);
4365
- });
4391
+ }, Arg("pos"), Arg("value").keepAlive());
4366
4392
 
4367
4393
  rb_define_alias(klass_, "push_back", "push");
4368
4394
  rb_define_alias(klass_, "<<", "push");
@@ -4496,7 +4522,19 @@ namespace Rice
4496
4522
  case RUBY_T_ARRAY:
4497
4523
  if constexpr (std::is_default_constructible_v<T>)
4498
4524
  {
4499
- return Convertible::Exact;
4525
+ // For proper overload resolution when a function has multiple vector type
4526
+ // overloads (e.g., vector<A>& and vector<B>&), we must check if the array
4527
+ // elements can actually be converted to T. Otherwise all vector overloads
4528
+ // score equally and the wrong one may be selected.
4529
+ long size = RARRAY_LEN(value);
4530
+ if (size == 0)
4531
+ {
4532
+ return Convertible::Exact;
4533
+ }
4534
+
4535
+ From_Ruby<remove_cv_recursive_t<T>> fromRuby;
4536
+ VALUE first = rb_ary_entry(value, 0);
4537
+ return fromRuby.is_convertible(first);
4500
4538
  }
4501
4539
  default:
4502
4540
  return Convertible::None;
@@ -4552,7 +4590,19 @@ namespace Rice
4552
4590
  case RUBY_T_ARRAY:
4553
4591
  if constexpr (std::is_default_constructible_v<T>)
4554
4592
  {
4555
- return Convertible::Exact;
4593
+ // For proper overload resolution when a function has multiple vector type
4594
+ // overloads (e.g., vector<A>& and vector<B>&), we must check if the array
4595
+ // elements can actually be converted to T. Otherwise all vector overloads
4596
+ // score equally and the wrong one may be selected.
4597
+ long size = RARRAY_LEN(value);
4598
+ if (size == 0)
4599
+ {
4600
+ return Convertible::Exact;
4601
+ }
4602
+
4603
+ From_Ruby<remove_cv_recursive_t<T>> fromRuby;
4604
+ VALUE first = rb_ary_entry(value, 0);
4605
+ return fromRuby.is_convertible(first);
4556
4606
  }
4557
4607
  default:
4558
4608
  return Convertible::None;
@@ -4613,7 +4663,19 @@ namespace Rice
4613
4663
  case RUBY_T_ARRAY:
4614
4664
  if constexpr (std::is_default_constructible_v<T>)
4615
4665
  {
4616
- return Convertible::Exact;
4666
+ // For proper overload resolution when a function has multiple vector type
4667
+ // overloads (e.g., vector<A>& and vector<B>&), we must check if the array
4668
+ // elements can actually be converted to T. Otherwise all vector overloads
4669
+ // score equally and the wrong one may be selected.
4670
+ long size = RARRAY_LEN(value);
4671
+ if (size == 0)
4672
+ {
4673
+ return Convertible::Exact;
4674
+ }
4675
+
4676
+ From_Ruby<remove_cv_recursive_t<T>> fromRuby;
4677
+ VALUE first = rb_ary_entry(value, 0);
4678
+ return fromRuby.is_convertible(first);
4617
4679
  }
4618
4680
  default:
4619
4681
  return Convertible::None;