rice 4.7.1 → 4.9.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 (160) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +37 -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 +58 -141
  7. data/include/rice/api.hpp +261 -0
  8. data/include/rice/rice.hpp +2459 -1693
  9. data/include/rice/stl.hpp +450 -546
  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 +21 -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 +5 -10
  17. data/lib/rice/rbs.rb +6 -6
  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 +33 -31
  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 +7 -2
  42. data/rice/cpp_api/Class.ipp +9 -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 +10 -4
  47. data/rice/cpp_api/Object.ipp +20 -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/Forwards.hpp +18 -0
  53. data/rice/detail/Forwards.ipp +60 -0
  54. data/rice/detail/InstanceRegistry.hpp +0 -2
  55. data/rice/detail/Native.hpp +31 -21
  56. data/rice/detail/Native.ipp +282 -130
  57. data/rice/detail/NativeAttributeGet.hpp +5 -7
  58. data/rice/detail/NativeAttributeGet.ipp +26 -26
  59. data/rice/detail/NativeAttributeSet.hpp +2 -4
  60. data/rice/detail/NativeAttributeSet.ipp +20 -16
  61. data/rice/detail/NativeCallback.hpp +77 -0
  62. data/rice/detail/NativeCallback.ipp +280 -0
  63. data/rice/detail/NativeFunction.hpp +11 -21
  64. data/rice/detail/NativeFunction.ipp +58 -119
  65. data/rice/detail/NativeInvoker.hpp +4 -4
  66. data/rice/detail/NativeInvoker.ipp +7 -7
  67. data/rice/detail/NativeIterator.hpp +2 -4
  68. data/rice/detail/NativeIterator.ipp +18 -14
  69. data/rice/detail/NativeMethod.hpp +10 -20
  70. data/rice/detail/NativeMethod.ipp +54 -114
  71. data/rice/detail/NativeProc.hpp +5 -7
  72. data/rice/detail/NativeProc.ipp +39 -28
  73. data/rice/detail/NativeRegistry.hpp +1 -1
  74. data/rice/detail/NativeRegistry.ipp +29 -0
  75. data/rice/detail/Parameter.hpp +15 -8
  76. data/rice/detail/Parameter.ipp +102 -43
  77. data/rice/detail/Proc.ipp +14 -28
  78. data/rice/detail/RubyType.ipp +2 -53
  79. data/rice/detail/Type.hpp +23 -7
  80. data/rice/detail/Type.ipp +77 -93
  81. data/rice/detail/TypeRegistry.ipp +5 -4
  82. data/rice/detail/Wrapper.hpp +13 -12
  83. data/rice/detail/Wrapper.ipp +97 -44
  84. data/rice/detail/from_ruby.hpp +8 -6
  85. data/rice/detail/from_ruby.ipp +306 -173
  86. data/rice/detail/ruby.hpp +23 -0
  87. data/rice/libc/file.hpp +4 -4
  88. data/rice/rice.hpp +9 -8
  89. data/rice/rice_api/Native.ipp +5 -1
  90. data/rice/rice_api/NativeRegistry.ipp +14 -1
  91. data/rice/rice_api/Parameter.ipp +1 -1
  92. data/rice/ruby_mark.hpp +2 -1
  93. data/rice/stl/complex.ipp +12 -8
  94. data/rice/stl/map.ipp +27 -22
  95. data/rice/stl/monostate.ipp +16 -12
  96. data/rice/stl/multimap.hpp +0 -2
  97. data/rice/stl/multimap.ipp +27 -22
  98. data/rice/stl/optional.ipp +27 -11
  99. data/rice/stl/pair.ipp +5 -5
  100. data/rice/stl/reference_wrapper.ipp +5 -4
  101. data/rice/stl/set.ipp +16 -16
  102. data/rice/stl/shared_ptr.hpp +9 -9
  103. data/rice/stl/shared_ptr.ipp +52 -185
  104. data/rice/stl/string.ipp +18 -18
  105. data/rice/stl/string_view.ipp +1 -1
  106. data/rice/stl/tuple.ipp +15 -36
  107. data/rice/stl/unique_ptr.hpp +9 -3
  108. data/rice/stl/unique_ptr.ipp +86 -120
  109. data/rice/stl/unordered_map.ipp +20 -15
  110. data/rice/stl/variant.ipp +37 -21
  111. data/rice/stl/vector.ipp +41 -36
  112. data/rice/traits/function_traits.hpp +19 -19
  113. data/rice/traits/method_traits.hpp +4 -4
  114. data/rice/traits/rice_traits.hpp +162 -39
  115. data/rice.gemspec +1 -3
  116. data/test/test_Array.cpp +261 -3
  117. data/test/test_Attribute.cpp +6 -3
  118. data/test/test_Buffer.cpp +6 -42
  119. data/test/test_Callback.cpp +77 -23
  120. data/test/test_Data_Object.cpp +1 -1
  121. data/test/test_Data_Type.cpp +21 -22
  122. data/test/test_Director.cpp +2 -4
  123. data/test/test_Enum.cpp +34 -5
  124. data/test/test_File.cpp +9 -5
  125. data/test/test_From_Ruby.cpp +4 -3
  126. data/test/test_GVL.cpp +3 -3
  127. data/test/test_Hash.cpp +1 -1
  128. data/test/test_Inheritance.cpp +14 -14
  129. data/test/test_Iterator.cpp +54 -22
  130. data/test/test_Keep_Alive.cpp +1 -1
  131. data/test/test_Keep_Alive_No_Wrapper.cpp +7 -3
  132. data/test/test_Module.cpp +5 -5
  133. data/test/test_Overloads.cpp +345 -48
  134. data/test/test_Proc.cpp +54 -0
  135. data/test/test_Reference.cpp +181 -0
  136. data/test/test_Self.cpp +2 -2
  137. data/test/test_Stl_Set.cpp +6 -6
  138. data/test/test_Stl_SharedPtr.cpp +172 -33
  139. data/test/test_Stl_String_View.cpp +4 -2
  140. data/test/test_Stl_Tuple.cpp +1 -1
  141. data/test/test_Stl_UniquePtr.cpp +48 -3
  142. data/test/test_Stl_Variant.cpp +6 -14
  143. data/test/test_Stl_Vector.cpp +61 -30
  144. data/test/test_String.cpp +4 -2
  145. data/test/test_Struct.cpp +1 -1
  146. data/test/test_Symbol.cpp +1 -1
  147. data/test/test_To_Ruby.cpp +1 -0
  148. data/test/test_Type.cpp +36 -35
  149. data/test/test_global_functions.cpp +1 -1
  150. data/test/unittest.cpp +1 -1
  151. data/test/unittest.hpp +5 -5
  152. metadata +12 -10
  153. data/rice/Function.hpp +0 -17
  154. data/rice/Function.ipp +0 -13
  155. data/rice/detail/MethodInfo.hpp +0 -48
  156. data/rice/detail/MethodInfo.ipp +0 -99
  157. data/rice/detail/NativeCallbackFFI.hpp +0 -55
  158. data/rice/detail/NativeCallbackFFI.ipp +0 -152
  159. data/rice/detail/NativeCallbackSimple.hpp +0 -30
  160. data/rice/detail/NativeCallbackSimple.ipp +0 -29
data/include/rice/stl.hpp CHANGED
@@ -1,3 +1,30 @@
1
+ // This file is part of [rice](https://github.com/ruby-rice/rice).
2
+ //
3
+ // Copyright (C) 2025 Jason Roelofs <jasongroelofs@gmail.com>
4
+ // Paul Brannan <curlypaul924@gmail.com>,
5
+ // Charlie Savage
6
+ //
7
+ // Redistribution and use in source and binary forms, with or without
8
+ // modification, are permitted provided that the following conditions
9
+ // are met:
10
+ //
11
+ // 1. Redistributions of source code must retain the above copyright
12
+ // notice, this list of conditions and the following disclaimer.
13
+ // 2. Redistributions in binary form must reproduce the above copyright
14
+ // notice, this list of conditions and the following disclaimer in the
15
+ // documentation and/or other materials provided with the distribution.
16
+ //
17
+ // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18
+ // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19
+ // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20
+ // IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21
+ // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22
+ // NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
+ // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
+ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26
+ // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+
1
28
  #ifndef Rice__stl__hpp_
2
29
  #define Rice__stl__hpp_
3
30
 
@@ -162,7 +189,7 @@ namespace Rice::detail
162
189
  public:
163
190
  To_Ruby() = default;
164
191
 
165
- explicit To_Ruby(Return* returnInfo) : returnInfo_(returnInfo)
192
+ explicit To_Ruby(Arg* arg) : arg_(arg)
166
193
  {
167
194
  }
168
195
 
@@ -172,7 +199,7 @@ namespace Rice::detail
172
199
  }
173
200
 
174
201
  private:
175
- Return* returnInfo_ = nullptr;
202
+ Arg* arg_ = nullptr;
176
203
  };
177
204
 
178
205
  template<>
@@ -181,7 +208,7 @@ namespace Rice::detail
181
208
  public:
182
209
  To_Ruby() = default;
183
210
 
184
- explicit To_Ruby(Return* returnInfo) : returnInfo_(returnInfo)
211
+ explicit To_Ruby(Arg* arg) : arg_(arg)
185
212
  {
186
213
  }
187
214
 
@@ -191,7 +218,7 @@ namespace Rice::detail
191
218
  }
192
219
 
193
220
  private:
194
- Return* returnInfo_ = nullptr;
221
+ Arg* arg_ = nullptr;
195
222
  };
196
223
 
197
224
  template<int N>
@@ -200,7 +227,7 @@ namespace Rice::detail
200
227
  public:
201
228
  To_Ruby() = default;
202
229
 
203
- explicit To_Ruby(Return* returnInfo) : returnInfo_(returnInfo)
230
+ explicit To_Ruby(Arg* arg) : arg_(arg)
204
231
  {
205
232
  }
206
233
 
@@ -211,7 +238,7 @@ namespace Rice::detail
211
238
  return dataObject.value();
212
239
  }
213
240
  private:
214
- Return* returnInfo_ = nullptr;
241
+ Arg* arg_ = nullptr;
215
242
  };
216
243
 
217
244
  template<>
@@ -220,14 +247,14 @@ namespace Rice::detail
220
247
  public:
221
248
  To_Ruby() = default;
222
249
 
223
- explicit To_Ruby(Return* returnInfo) : returnInfo_(returnInfo)
250
+ explicit To_Ruby(Arg* arg) : arg_(arg)
224
251
  {
225
252
  }
226
253
 
227
254
  VALUE convert(const std::string* value)
228
255
  {
229
- bool isOwner = this->returnInfo_ && this->returnInfo_->isOwner();
230
- bool isBuffer = this->returnInfo_ && this->returnInfo_->isBuffer();
256
+ bool isOwner = this->arg_ && this->arg_->isOwner();
257
+ bool isBuffer = dynamic_cast<ReturnBuffer*>(this->arg_) ? true : false;
231
258
 
232
259
  if (isBuffer)
233
260
  {
@@ -241,7 +268,7 @@ namespace Rice::detail
241
268
  }
242
269
 
243
270
  private:
244
- Return* returnInfo_ = nullptr;
271
+ Arg* arg_ = nullptr;
245
272
  };
246
273
 
247
274
  template<>
@@ -250,7 +277,7 @@ namespace Rice::detail
250
277
  public:
251
278
  To_Ruby() = default;
252
279
 
253
- explicit To_Ruby(Return* returnInfo) : returnInfo_(returnInfo)
280
+ explicit To_Ruby(Arg* arg) : arg_(arg)
254
281
  {
255
282
  }
256
283
 
@@ -260,7 +287,7 @@ namespace Rice::detail
260
287
  }
261
288
 
262
289
  private:
263
- Return* returnInfo_ = nullptr;
290
+ Arg* arg_ = nullptr;
264
291
  };
265
292
 
266
293
  /*template<>
@@ -269,7 +296,7 @@ namespace Rice::detail
269
296
  public:
270
297
  To_Ruby() = default;
271
298
 
272
- explicit To_Ruby(Return* returnInfo) : returnInfo_(returnInfo)
299
+ explicit To_Ruby(Arg* arg) : arg_(arg)
273
300
  {
274
301
  }
275
302
 
@@ -281,7 +308,7 @@ namespace Rice::detail
281
308
  }
282
309
 
283
310
  private:
284
- Return* returnInfo_ = nullptr;
311
+ Arg* arg_ = nullptr;
285
312
  };*/
286
313
 
287
314
  template<>
@@ -294,7 +321,7 @@ namespace Rice::detail
294
321
  {
295
322
  }
296
323
 
297
- Convertible is_convertible(VALUE value)
324
+ double is_convertible(VALUE value)
298
325
  {
299
326
  switch (rb_type(value))
300
327
  {
@@ -326,7 +353,7 @@ namespace Rice::detail
326
353
  {
327
354
  }
328
355
 
329
- Convertible is_convertible(VALUE value)
356
+ double is_convertible(VALUE value)
330
357
  {
331
358
  switch (rb_type(value))
332
359
  {
@@ -360,7 +387,7 @@ namespace Rice::detail
360
387
  {
361
388
  }
362
389
 
363
- Convertible is_convertible(VALUE value)
390
+ double is_convertible(VALUE value)
364
391
  {
365
392
  switch (rb_type(value))
366
393
  {
@@ -394,7 +421,7 @@ namespace Rice::detail
394
421
  {
395
422
  }
396
423
 
397
- Convertible is_convertible(VALUE value)
424
+ double is_convertible(VALUE value)
398
425
  {
399
426
  switch (rb_type(value))
400
427
  {
@@ -489,7 +516,7 @@ namespace Rice::detail
489
516
  {
490
517
  }
491
518
 
492
- Convertible is_convertible(VALUE value)
519
+ double is_convertible(VALUE value)
493
520
  {
494
521
  switch (rb_type(value))
495
522
  {
@@ -540,7 +567,7 @@ namespace Rice::detail
540
567
  public:
541
568
  To_Ruby() = default;
542
569
 
543
- explicit To_Ruby(Return* returnInfo) : returnInfo_(returnInfo)
570
+ explicit To_Ruby(Arg* arg) : arg_(arg)
544
571
  {
545
572
  }
546
573
 
@@ -553,7 +580,7 @@ namespace Rice::detail
553
580
  }
554
581
 
555
582
  private:
556
- Return* returnInfo_ = nullptr;
583
+ Arg* arg_ = nullptr;
557
584
  };
558
585
 
559
586
  template<typename T>
@@ -562,7 +589,7 @@ namespace Rice::detail
562
589
  public:
563
590
  To_Ruby() = default;
564
591
 
565
- explicit To_Ruby(Return* returnInfo) : returnInfo_(returnInfo)
592
+ explicit To_Ruby(Arg* arg) : arg_(arg)
566
593
  {
567
594
  }
568
595
 
@@ -575,7 +602,7 @@ namespace Rice::detail
575
602
  }
576
603
 
577
604
  private:
578
- Return* returnInfo_ = nullptr;
605
+ Arg* arg_ = nullptr;
579
606
  };
580
607
 
581
608
  template<typename T>
@@ -584,11 +611,11 @@ namespace Rice::detail
584
611
  public:
585
612
  From_Ruby() = default;
586
613
 
587
- explicit From_Ruby(Arg* arg)
614
+ explicit From_Ruby(Arg* arg) :arg_(arg)
588
615
  {
589
616
  }
590
617
 
591
- Convertible is_convertible(VALUE value)
618
+ double is_convertible(VALUE value)
592
619
  {
593
620
  switch (rb_type(value))
594
621
  {
@@ -607,6 +634,9 @@ namespace Rice::detail
607
634
 
608
635
  return std::complex<T>(From_Ruby<T>().convert(real), From_Ruby<T>().convert(imaginary));
609
636
  }
637
+
638
+ private:
639
+ Arg* arg_ = nullptr;
610
640
  };
611
641
 
612
642
  template<typename T>
@@ -615,11 +645,11 @@ namespace Rice::detail
615
645
  public:
616
646
  From_Ruby() = default;
617
647
 
618
- explicit From_Ruby(Arg* arg)
648
+ explicit From_Ruby(Arg* arg) : arg_(arg)
619
649
  {
620
650
  }
621
651
 
622
- Convertible is_convertible(VALUE value)
652
+ double is_convertible(VALUE value)
623
653
  {
624
654
  switch (rb_type(value))
625
655
  {
@@ -641,6 +671,7 @@ namespace Rice::detail
641
671
  }
642
672
 
643
673
  private:
674
+ Arg* arg_ = nullptr;
644
675
  std::complex<T> converted_;
645
676
  };
646
677
  }
@@ -715,17 +746,17 @@ namespace Rice::detail
715
746
  public:
716
747
  To_Ruby() = default;
717
748
 
718
- explicit To_Ruby(Return* returnInfo) : returnInfo_(returnInfo)
749
+ explicit To_Ruby(Arg* arg) : arg_(arg)
719
750
  {
720
751
  }
721
752
 
722
- VALUE convert(const std::nullopt_t& _)
753
+ VALUE convert(const std::nullopt_t&)
723
754
  {
724
755
  return Qnil;
725
756
  }
726
757
 
727
758
  private:
728
- Return* returnInfo_ = nullptr;
759
+ Arg* arg_ = nullptr;
729
760
  };
730
761
 
731
762
  template<typename T>
@@ -734,7 +765,7 @@ namespace Rice::detail
734
765
  public:
735
766
  To_Ruby() = default;
736
767
 
737
- explicit To_Ruby(Return* returnInfo) : returnInfo_(returnInfo)
768
+ explicit To_Ruby(Arg* arg) : arg_(arg)
738
769
  {
739
770
  }
740
771
 
@@ -750,8 +781,20 @@ namespace Rice::detail
750
781
  }
751
782
  }
752
783
 
784
+ VALUE convert(const std::optional<T>& data)
785
+ {
786
+ if (data.has_value())
787
+ {
788
+ return To_Ruby<T>().convert(data.value());
789
+ }
790
+ else
791
+ {
792
+ return Qnil;
793
+ }
794
+ }
795
+
753
796
  private:
754
- Return* returnInfo_ = nullptr;
797
+ Arg* arg_ = nullptr;
755
798
  };
756
799
 
757
800
  template<typename T>
@@ -760,7 +803,7 @@ namespace Rice::detail
760
803
  public:
761
804
  To_Ruby() = default;
762
805
 
763
- explicit To_Ruby(Return* returnInfo) : returnInfo_(returnInfo)
806
+ explicit To_Ruby(Arg* arg) : arg_(arg)
764
807
  {
765
808
  }
766
809
 
@@ -777,7 +820,7 @@ namespace Rice::detail
777
820
  }
778
821
 
779
822
  private:
780
- Return* returnInfo_ = nullptr;
823
+ Arg* arg_ = nullptr;
781
824
  };
782
825
 
783
826
  template<typename T>
@@ -786,11 +829,11 @@ namespace Rice::detail
786
829
  public:
787
830
  From_Ruby() = default;
788
831
 
789
- explicit From_Ruby(Arg* arg)
832
+ explicit From_Ruby(Arg* arg) : arg_(arg)
790
833
  {
791
834
  }
792
835
 
793
- Convertible is_convertible(VALUE value)
836
+ double is_convertible(VALUE value)
794
837
  {
795
838
  switch (rb_type(value))
796
839
  {
@@ -813,6 +856,9 @@ namespace Rice::detail
813
856
  return From_Ruby<T>().convert(value);
814
857
  }
815
858
  }
859
+
860
+ private:
861
+ Arg* arg_ = nullptr;
816
862
  };
817
863
 
818
864
  template<typename T>
@@ -821,11 +867,11 @@ namespace Rice::detail
821
867
  public:
822
868
  From_Ruby() = default;
823
869
 
824
- explicit From_Ruby(Arg* arg)
870
+ explicit From_Ruby(Arg* arg) : arg_(arg)
825
871
  {
826
872
  }
827
873
 
828
- Convertible is_convertible(VALUE value)
874
+ double is_convertible(VALUE value)
829
875
  {
830
876
  switch (rb_type(value))
831
877
  {
@@ -850,6 +896,7 @@ namespace Rice::detail
850
896
  return this->converted_;
851
897
  }
852
898
  private:
899
+ Arg* arg_ = nullptr;
853
900
  std::optional<T> converted_;
854
901
  };
855
902
  }
@@ -884,7 +931,7 @@ namespace Rice::detail
884
931
  public:
885
932
  To_Ruby() = default;
886
933
 
887
- explicit To_Ruby(Return* returnInfo) : returnInfo_(returnInfo)
934
+ explicit To_Ruby(Arg* arg) : arg_(arg)
888
935
  {
889
936
  }
890
937
 
@@ -894,7 +941,7 @@ namespace Rice::detail
894
941
  }
895
942
 
896
943
  private:
897
- Return* returnInfo_ = nullptr;
944
+ Arg* arg_ = nullptr;
898
945
  };
899
946
 
900
947
  template<typename T>
@@ -903,11 +950,11 @@ namespace Rice::detail
903
950
  public:
904
951
  From_Ruby() = default;
905
952
 
906
- explicit From_Ruby(Arg* arg)
953
+ explicit From_Ruby(Arg* arg) : arg_(arg)
907
954
  {
908
955
  }
909
956
 
910
- Convertible is_convertible(VALUE value)
957
+ double is_convertible(VALUE value)
911
958
  {
912
959
  return this->converter_.is_convertible(value);
913
960
  }
@@ -918,6 +965,7 @@ namespace Rice::detail
918
965
  }
919
966
 
920
967
  private:
968
+ Arg* arg_ = nullptr;
921
969
  From_Ruby<T&> converter_;
922
970
  };
923
971
  }
@@ -997,11 +1045,11 @@ namespace Rice
997
1045
  }
998
1046
  else
999
1047
  {
1000
- klass_.define_method("to_s", [](const T& pair)
1001
- {
1002
- return "[Not printable]";
1003
- });
1004
- }
1048
+ klass_.define_method("to_s", [](const T&)
1049
+ {
1050
+ return "[Not printable]";
1051
+ });
1052
+ }
1005
1053
  }
1006
1054
 
1007
1055
  private:
@@ -1175,20 +1223,25 @@ namespace Rice
1175
1223
  {
1176
1224
  if constexpr (detail::is_comparable_v<Mapped_T>)
1177
1225
  {
1178
- klass_.define_method("value?", [](T& map, Mapped_T& value) -> bool
1179
- {
1180
- auto it = std::find_if(map.begin(), map.end(),
1181
- [&value](auto& pair)
1182
- {
1183
- return pair.second == value;
1184
- });
1226
+ klass_.define_method("==", [](T& map, T& other)->bool
1227
+ {
1228
+ return map == other;
1229
+ })
1230
+ .define_method("value?", [](T& map, Mapped_T& value) -> bool
1231
+ {
1232
+ auto it = std::find_if(map.begin(), map.end(),
1233
+ [&value](auto& pair)
1234
+ {
1235
+ return pair.second == value;
1236
+ });
1185
1237
 
1186
- return it != map.end();
1238
+ return it != map.end();
1187
1239
  });
1240
+ rb_define_alias(klass_, "eql?", "==");
1188
1241
  }
1189
1242
  else
1190
1243
  {
1191
- klass_.define_method("value?", [](T& map, Mapped_T& value) -> bool
1244
+ klass_.define_method("value?", [](T&, Mapped_T&) -> bool
1192
1245
  {
1193
1246
  return false;
1194
1247
  });
@@ -1273,10 +1326,10 @@ namespace Rice
1273
1326
  }
1274
1327
  else
1275
1328
  {
1276
- klass_.define_method("to_s", [](const T& map)
1277
- {
1278
- return "[Not printable]";
1279
- });
1329
+ klass_.define_method("to_s", [](const T&)
1330
+ {
1331
+ return "[Not printable]";
1332
+ });
1280
1333
  }
1281
1334
  }
1282
1335
 
@@ -1367,7 +1420,7 @@ namespace Rice
1367
1420
  {
1368
1421
  }
1369
1422
 
1370
- Convertible is_convertible(VALUE value)
1423
+ double is_convertible(VALUE value)
1371
1424
  {
1372
1425
  switch (rb_type(value))
1373
1426
  {
@@ -1375,7 +1428,7 @@ namespace Rice
1375
1428
  return Data_Type<std::map<T, U>>::is_descendant(value) ? Convertible::Exact : Convertible::None;
1376
1429
  break;
1377
1430
  case RUBY_T_HASH:
1378
- return Convertible::Cast;
1431
+ return Convertible::Exact;
1379
1432
  break;
1380
1433
  default:
1381
1434
  return Convertible::None;
@@ -1401,7 +1454,7 @@ namespace Rice
1401
1454
  }
1402
1455
  default:
1403
1456
  {
1404
- throw Exception(rb_eTypeError, "wrong argument type %s (expected % s)",
1457
+ throw Exception(rb_eTypeError, "wrong argument type %s (expected %s)",
1405
1458
  detail::protect(rb_obj_classname, value), "std::map");
1406
1459
  }
1407
1460
  }
@@ -1421,7 +1474,7 @@ namespace Rice
1421
1474
  {
1422
1475
  }
1423
1476
 
1424
- Convertible is_convertible(VALUE value)
1477
+ double is_convertible(VALUE value)
1425
1478
  {
1426
1479
  switch (rb_type(value))
1427
1480
  {
@@ -1429,7 +1482,7 @@ namespace Rice
1429
1482
  return Data_Type<std::map<T, U>>::is_descendant(value) ? Convertible::Exact : Convertible::None;
1430
1483
  break;
1431
1484
  case RUBY_T_HASH:
1432
- return Convertible::Cast;
1485
+ return Convertible::Exact;
1433
1486
  break;
1434
1487
  default:
1435
1488
  return Convertible::None;
@@ -1456,7 +1509,7 @@ namespace Rice
1456
1509
  }
1457
1510
  default:
1458
1511
  {
1459
- throw Exception(rb_eTypeError, "wrong argument type %s (expected % s)",
1512
+ throw Exception(rb_eTypeError, "wrong argument type %s (expected %s)",
1460
1513
  detail::protect(rb_obj_classname, value), "std::map");
1461
1514
  }
1462
1515
  }
@@ -1477,7 +1530,7 @@ namespace Rice
1477
1530
  {
1478
1531
  }
1479
1532
 
1480
- Convertible is_convertible(VALUE value)
1533
+ double is_convertible(VALUE value)
1481
1534
  {
1482
1535
  switch (rb_type(value))
1483
1536
  {
@@ -1488,7 +1541,7 @@ namespace Rice
1488
1541
  return Convertible::Exact;
1489
1542
  break;
1490
1543
  case RUBY_T_HASH:
1491
- return Convertible::Cast;
1544
+ return Convertible::Exact;
1492
1545
  break;
1493
1546
  default:
1494
1547
  return Convertible::None;
@@ -1515,7 +1568,7 @@ namespace Rice
1515
1568
  }
1516
1569
  default:
1517
1570
  {
1518
- throw Exception(rb_eTypeError, "wrong argument type %s (expected % s)",
1571
+ throw Exception(rb_eTypeError, "wrong argument type %s (expected %s)",
1519
1572
  detail::protect(rb_obj_classname, value), "std::map");
1520
1573
  }
1521
1574
  }
@@ -1556,18 +1609,18 @@ namespace Rice::detail
1556
1609
  public:
1557
1610
  To_Ruby() = default;
1558
1611
 
1559
- explicit To_Ruby(Return* returnInfo) : returnInfo_(returnInfo)
1612
+ explicit To_Ruby(Arg* arg) : arg_(arg)
1560
1613
  {
1561
1614
  }
1562
1615
 
1563
- VALUE convert(const std::monostate& _)
1616
+ VALUE convert(const std::monostate&)
1564
1617
  {
1565
1618
  return Qnil;
1566
1619
  }
1567
1620
 
1568
1621
 
1569
1622
  private:
1570
- Return* returnInfo_ = nullptr;
1623
+ Arg* arg_ = nullptr;
1571
1624
  };
1572
1625
 
1573
1626
  template<>
@@ -1576,17 +1629,17 @@ namespace Rice::detail
1576
1629
  public:
1577
1630
  To_Ruby() = default;
1578
1631
 
1579
- explicit To_Ruby(Return* returnInfo) : returnInfo_(returnInfo)
1632
+ explicit To_Ruby(Arg* arg) : arg_(arg)
1580
1633
  {
1581
1634
  }
1582
1635
 
1583
- VALUE convert(const std::monostate& data)
1636
+ VALUE convert(const std::monostate&)
1584
1637
  {
1585
1638
  return Qnil;
1586
1639
  }
1587
1640
 
1588
1641
  private:
1589
- Return* returnInfo_ = nullptr;
1642
+ Arg* arg_ = nullptr;
1590
1643
  };
1591
1644
 
1592
1645
  template<>
@@ -1595,13 +1648,13 @@ namespace Rice::detail
1595
1648
  public:
1596
1649
  From_Ruby() = default;
1597
1650
 
1598
- explicit From_Ruby(Arg* arg)
1651
+ explicit From_Ruby(Arg* arg) : arg_(arg)
1599
1652
  {
1600
1653
  }
1601
1654
 
1602
- Convertible is_convertible(VALUE value)
1655
+ double is_convertible(VALUE value)
1603
1656
  {
1604
- return value == Qnil ? Convertible::Exact : Convertible::None;
1657
+ return value == Qnil ? 1.0 : 0.0;
1605
1658
  }
1606
1659
 
1607
1660
  std::monostate convert(VALUE value)
@@ -1615,6 +1668,9 @@ namespace Rice::detail
1615
1668
  throw std::runtime_error("Can only convert nil values to std::monostate");
1616
1669
  }
1617
1670
  }
1671
+
1672
+ private:
1673
+ Arg* arg_ = nullptr;
1618
1674
  };
1619
1675
 
1620
1676
  template<>
@@ -1623,13 +1679,13 @@ namespace Rice::detail
1623
1679
  public:
1624
1680
  From_Ruby() = default;
1625
1681
 
1626
- explicit From_Ruby(Arg* arg)
1682
+ explicit From_Ruby(Arg* arg) : arg_(arg)
1627
1683
  {
1628
1684
  }
1629
1685
 
1630
- Convertible is_convertible(VALUE value)
1686
+ double is_convertible(VALUE value)
1631
1687
  {
1632
- return value == Qnil ? Convertible::Exact : Convertible::None;
1688
+ return value == Qnil ? 1.0 : 0.0;
1633
1689
  }
1634
1690
 
1635
1691
  std::monostate& convert(VALUE value)
@@ -1645,6 +1701,7 @@ namespace Rice::detail
1645
1701
  }
1646
1702
 
1647
1703
  private:
1704
+ Arg* arg_ = nullptr;
1648
1705
  std::monostate converted_ = std::monostate();
1649
1706
  };
1650
1707
  }
@@ -1652,8 +1709,6 @@ namespace Rice::detail
1652
1709
 
1653
1710
  // ========= multimap.hpp =========
1654
1711
 
1655
- #include <map>
1656
-
1657
1712
  namespace Rice
1658
1713
  {
1659
1714
  template<typename K, typename T>
@@ -1770,20 +1825,25 @@ namespace Rice
1770
1825
  {
1771
1826
  if constexpr (detail::is_comparable_v<Mapped_T>)
1772
1827
  {
1773
- klass_.define_method("value?", [](T& multimap, Mapped_T& value) -> bool
1774
- {
1775
- auto it = std::find_if(multimap.begin(), multimap.end(),
1776
- [&value](auto& pair)
1777
- {
1778
- return pair.second == value;
1779
- });
1828
+ klass_.define_method("==", [](T& multimap, T& other)->bool
1829
+ {
1830
+ return multimap == other;
1831
+ })
1832
+ .define_method("value?", [](T& multimap, Mapped_T& value) -> bool
1833
+ {
1834
+ auto it = std::find_if(multimap.begin(), multimap.end(),
1835
+ [&value](auto& pair)
1836
+ {
1837
+ return pair.second == value;
1838
+ });
1780
1839
 
1781
- return it != multimap.end();
1840
+ return it != multimap.end();
1782
1841
  });
1842
+ rb_define_alias(klass_, "eql?", "==");
1783
1843
  }
1784
1844
  else
1785
1845
  {
1786
- klass_.define_method("value?", [](T& multimap, Mapped_T& value) -> bool
1846
+ klass_.define_method("value?", [](T&, Mapped_T&) -> bool
1787
1847
  {
1788
1848
  return false;
1789
1849
  });
@@ -1852,10 +1912,10 @@ namespace Rice
1852
1912
  }
1853
1913
  else
1854
1914
  {
1855
- klass_.define_method("to_s", [](const T& multimap)
1856
- {
1857
- return "[Not printable]";
1858
- });
1915
+ klass_.define_method("to_s", [](const T&)
1916
+ {
1917
+ return "[Not printable]";
1918
+ });
1859
1919
  }
1860
1920
  }
1861
1921
 
@@ -1943,7 +2003,7 @@ namespace Rice
1943
2003
  {
1944
2004
  }
1945
2005
 
1946
- Convertible is_convertible(VALUE value)
2006
+ double is_convertible(VALUE value)
1947
2007
  {
1948
2008
  switch (rb_type(value))
1949
2009
  {
@@ -1951,7 +2011,7 @@ namespace Rice
1951
2011
  return Data_Type<std::multimap<T, U>>::is_descendant(value) ? Convertible::Exact : Convertible::None;
1952
2012
  break;
1953
2013
  case RUBY_T_HASH:
1954
- return Convertible::Cast;
2014
+ return Convertible::Exact;
1955
2015
  break;
1956
2016
  default:
1957
2017
  return Convertible::None;
@@ -1977,7 +2037,7 @@ namespace Rice
1977
2037
  }
1978
2038
  default:
1979
2039
  {
1980
- throw Exception(rb_eTypeError, "wrong argument type %s (expected % s)",
2040
+ throw Exception(rb_eTypeError, "wrong argument type %s (expected %s)",
1981
2041
  detail::protect(rb_obj_classname, value), "std::multimap");
1982
2042
  }
1983
2043
  }
@@ -1997,7 +2057,7 @@ namespace Rice
1997
2057
  {
1998
2058
  }
1999
2059
 
2000
- Convertible is_convertible(VALUE value)
2060
+ double is_convertible(VALUE value)
2001
2061
  {
2002
2062
  switch (rb_type(value))
2003
2063
  {
@@ -2005,7 +2065,7 @@ namespace Rice
2005
2065
  return Data_Type<std::multimap<T, U>>::is_descendant(value) ? Convertible::Exact : Convertible::None;
2006
2066
  break;
2007
2067
  case RUBY_T_HASH:
2008
- return Convertible::Cast;
2068
+ return Convertible::Exact;
2009
2069
  break;
2010
2070
  default:
2011
2071
  return Convertible::None;
@@ -2032,7 +2092,7 @@ namespace Rice
2032
2092
  }
2033
2093
  default:
2034
2094
  {
2035
- throw Exception(rb_eTypeError, "wrong argument type %s (expected % s)",
2095
+ throw Exception(rb_eTypeError, "wrong argument type %s (expected %s)",
2036
2096
  detail::protect(rb_obj_classname, value), "std::multimap");
2037
2097
  }
2038
2098
  }
@@ -2053,7 +2113,7 @@ namespace Rice
2053
2113
  {
2054
2114
  }
2055
2115
 
2056
- Convertible is_convertible(VALUE value)
2116
+ double is_convertible(VALUE value)
2057
2117
  {
2058
2118
  switch (rb_type(value))
2059
2119
  {
@@ -2064,7 +2124,7 @@ namespace Rice
2064
2124
  return Convertible::Exact;
2065
2125
  break;
2066
2126
  case RUBY_T_HASH:
2067
- return Convertible::Cast;
2127
+ return Convertible::Exact;
2068
2128
  break;
2069
2129
  default:
2070
2130
  return Convertible::None;
@@ -2091,7 +2151,7 @@ namespace Rice
2091
2151
  }
2092
2152
  default:
2093
2153
  {
2094
- throw Exception(rb_eTypeError, "wrong argument type %s (expected % s)",
2154
+ throw Exception(rb_eTypeError, "wrong argument type %s (expected %s)",
2095
2155
  detail::protect(rb_obj_classname, value), "std::multimap");
2096
2156
  }
2097
2157
  }
@@ -2333,10 +2393,10 @@ namespace Rice
2333
2393
  }
2334
2394
  else
2335
2395
  {
2336
- klass_.define_method("to_s", [](const T& self)
2337
- {
2338
- return "[Not printable]";
2339
- });
2396
+ klass_.define_method("to_s", [](const T&)
2397
+ {
2398
+ return "[Not printable]";
2399
+ });
2340
2400
  }
2341
2401
  }
2342
2402
 
@@ -2423,7 +2483,7 @@ namespace Rice
2423
2483
  {
2424
2484
  }
2425
2485
 
2426
- Convertible is_convertible(VALUE value)
2486
+ double is_convertible(VALUE value)
2427
2487
  {
2428
2488
  switch (rb_type(value))
2429
2489
  {
@@ -2435,7 +2495,7 @@ namespace Rice
2435
2495
  Object object(value);
2436
2496
  if (object.class_name().str() == setName)
2437
2497
  {
2438
- return Convertible::Cast;
2498
+ return Convertible::Exact;
2439
2499
  }
2440
2500
  }
2441
2501
  default:
@@ -2459,12 +2519,12 @@ namespace Rice
2459
2519
  {
2460
2520
  return toSet<T>(value);
2461
2521
  }
2462
- throw Exception(rb_eTypeError, "wrong argument type %s (expected % s)",
2522
+ throw Exception(rb_eTypeError, "wrong argument type %s (expected %s)",
2463
2523
  detail::protect(rb_obj_classname, value), "std::set");
2464
2524
  }
2465
2525
  default:
2466
2526
  {
2467
- throw Exception(rb_eTypeError, "wrong argument type %s (expected % s)",
2527
+ throw Exception(rb_eTypeError, "wrong argument type %s (expected %s)",
2468
2528
  detail::protect(rb_obj_classname, value), "std::set");
2469
2529
  }
2470
2530
  }
@@ -2487,7 +2547,7 @@ namespace Rice
2487
2547
  {
2488
2548
  }
2489
2549
 
2490
- Convertible is_convertible(VALUE value)
2550
+ double is_convertible(VALUE value)
2491
2551
  {
2492
2552
  switch (rb_type(value))
2493
2553
  {
@@ -2499,7 +2559,7 @@ namespace Rice
2499
2559
  Object object(value);
2500
2560
  if (object.class_name().str() == setName)
2501
2561
  {
2502
- return Convertible::Cast;
2562
+ return Convertible::Exact;
2503
2563
  }
2504
2564
  }
2505
2565
  default:
@@ -2528,12 +2588,12 @@ namespace Rice
2528
2588
  return this->converted_;
2529
2589
  }
2530
2590
  }
2531
- throw Exception(rb_eTypeError, "wrong argument type %s (expected % s)",
2591
+ throw Exception(rb_eTypeError, "wrong argument type %s (expected %s)",
2532
2592
  detail::protect(rb_obj_classname, value), "std::set");
2533
2593
  }
2534
2594
  default:
2535
2595
  {
2536
- throw Exception(rb_eTypeError, "wrong argument type %s (expected % s)",
2596
+ throw Exception(rb_eTypeError, "wrong argument type %s (expected %s)",
2537
2597
  detail::protect(rb_obj_classname, value), "std::set");
2538
2598
  }
2539
2599
  }
@@ -2556,7 +2616,7 @@ namespace Rice
2556
2616
  {
2557
2617
  }
2558
2618
 
2559
- Convertible is_convertible(VALUE value)
2619
+ double is_convertible(VALUE value)
2560
2620
  {
2561
2621
  switch (rb_type(value))
2562
2622
  {
@@ -2571,7 +2631,7 @@ namespace Rice
2571
2631
  Object object(value);
2572
2632
  if (object.class_name().str() == setName)
2573
2633
  {
2574
- return Convertible::Cast;
2634
+ return Convertible::Exact;
2575
2635
  }
2576
2636
  }
2577
2637
  default:
@@ -2600,12 +2660,12 @@ namespace Rice
2600
2660
  return &this->converted_;
2601
2661
  }
2602
2662
  }
2603
- throw Exception(rb_eTypeError, "wrong argument type %s (expected % s)",
2663
+ throw Exception(rb_eTypeError, "wrong argument type %s (expected %s)",
2604
2664
  detail::protect(rb_obj_classname, value), "std::set");
2605
2665
  }
2606
2666
  default:
2607
2667
  {
2608
- throw Exception(rb_eTypeError, "wrong argument type %s (expected % s)",
2668
+ throw Exception(rb_eTypeError, "wrong argument type %s (expected %s)",
2609
2669
  detail::protect(rb_obj_classname, value), "std::set");
2610
2670
  }
2611
2671
  }
@@ -2621,33 +2681,32 @@ namespace Rice
2621
2681
 
2622
2682
  // ========= shared_ptr.hpp =========
2623
2683
 
2684
+ namespace Rice
2685
+ {
2686
+ template<typename T>
2687
+ Data_Type<std::shared_ptr<T>> define_shared_ptr(std::string klassName = "");
2688
+ }
2689
+
2624
2690
  namespace Rice::detail
2625
2691
  {
2626
2692
  template<typename T>
2627
2693
  class Wrapper<std::shared_ptr<T>> : public WrapperBase
2628
2694
  {
2629
2695
  public:
2630
- Wrapper(const std::shared_ptr<T>& data);
2696
+ Wrapper(rb_data_type_t* rb_data_type, const std::shared_ptr<T>& data);
2631
2697
  ~Wrapper();
2632
- void* get() override;
2633
- std::shared_ptr<T>& data();
2698
+ void* get(rb_data_type_t* requestedType) override;
2634
2699
 
2635
2700
  private:
2636
2701
  std::shared_ptr<T> data_;
2702
+ rb_data_type_t* inner_rb_data_type_;
2637
2703
  };
2638
2704
  }
2639
2705
 
2640
- namespace Rice
2641
- {
2642
- template<typename T>
2643
- Data_Type<std::shared_ptr<T>> define_shared_ptr(std::string klassName = "");
2644
- }
2645
-
2646
2706
 
2647
2707
  // --------- shared_ptr.ipp ---------
2648
2708
  #include <memory>
2649
2709
 
2650
- // --------- Enable creation of std::shared_ptr from Ruby ---------
2651
2710
  namespace Rice
2652
2711
  {
2653
2712
  template<typename T>
@@ -2670,7 +2729,24 @@ namespace Rice
2670
2729
 
2671
2730
  Identifier id(klassName);
2672
2731
  Data_Type_T result = define_class_under<detail::intrinsic_type<SharedPtr_T>>(rb_mStd, id).
2673
- define_constructor(Constructor<SharedPtr_T, typename SharedPtr_T::element_type*>(), Arg("value").takeOwnership());
2732
+ define_method("get", &SharedPtr_T::get).
2733
+ define_method("swap", &SharedPtr_T::swap).
2734
+ define_method("use_count", &SharedPtr_T::use_count).
2735
+ define_method("empty?", [](SharedPtr_T& self)->bool
2736
+ {
2737
+ return !self;
2738
+ });
2739
+
2740
+ if constexpr (!std::is_void_v<T>)
2741
+ {
2742
+ result.define_constructor(Constructor<SharedPtr_T, typename SharedPtr_T::element_type*>(), Arg("value").takeOwnership());
2743
+ }
2744
+
2745
+ // Setup delegation to forward T's methods via get (only for non-fundamental, non-void types)
2746
+ if constexpr (!std::is_void_v<T> && !std::is_fundamental_v<T>)
2747
+ {
2748
+ detail::define_forwarding(result.klass(), Data_Type<T>::klass());
2749
+ }
2674
2750
 
2675
2751
  return result;
2676
2752
  }
@@ -2680,31 +2756,47 @@ namespace Rice
2680
2756
  namespace Rice::detail
2681
2757
  {
2682
2758
  template<typename T>
2683
- inline Wrapper<std::shared_ptr<T>>::Wrapper(const std::shared_ptr<T>& data)
2684
- : data_(data)
2759
+ Wrapper<std::shared_ptr<T>>::Wrapper(rb_data_type_t* rb_data_type, const std::shared_ptr<T>& data)
2760
+ : WrapperBase(rb_data_type), data_(data)
2685
2761
  {
2686
- }
2762
+ using Intrinsic_T = intrinsic_type<T>;
2687
2763
 
2688
- template<typename T>
2689
- inline Wrapper<std::shared_ptr<T>>::~Wrapper()
2690
- {
2691
- Registries::instance.instances.remove(this->get());
2764
+ if constexpr (std::is_fundamental_v<Intrinsic_T>)
2765
+ {
2766
+ inner_rb_data_type_ = Data_Type<Pointer<Intrinsic_T>>::ruby_data_type();
2767
+ }
2768
+ else
2769
+ {
2770
+ inner_rb_data_type_ = Data_Type<Intrinsic_T>::ruby_data_type();
2771
+ }
2692
2772
  }
2693
2773
 
2694
2774
  template<typename T>
2695
- inline void* Wrapper<std::shared_ptr<T>>::get()
2775
+ Wrapper<std::shared_ptr<T>>::~Wrapper()
2696
2776
  {
2697
- return (void*)this->data_.get();
2777
+ Registries::instance.instances.remove(this->get(this->rb_data_type_));
2698
2778
  }
2699
2779
 
2700
2780
  template<typename T>
2701
- inline std::shared_ptr<T>& Wrapper<std::shared_ptr<T>>::data()
2781
+ void* Wrapper<std::shared_ptr<T>>::get(rb_data_type_t* requestedType)
2702
2782
  {
2703
- return data_;
2783
+ if (rb_typeddata_inherited_p(this->rb_data_type_, requestedType))
2784
+ {
2785
+ return &this->data_;
2786
+ }
2787
+ else if (rb_typeddata_inherited_p(this->inner_rb_data_type_, requestedType))
2788
+ {
2789
+ return this->data_.get();
2790
+ }
2791
+ else
2792
+ {
2793
+ throw Exception(rb_eTypeError, "wrong argument type (expected %s)",
2794
+ requestedType->wrap_struct_name);
2795
+ }
2704
2796
  }
2705
2797
  }
2706
2798
 
2707
- // --------- Type/To_Ruby/From_Ruby ---------
2799
+ // --------- Type ---------
2708
2800
  namespace Rice::detail
2709
2801
  {
2710
2802
  template<typename T>
@@ -2712,188 +2804,23 @@ namespace Rice::detail
2712
2804
  {
2713
2805
  static bool verify()
2714
2806
  {
2807
+ bool result = true;
2715
2808
  if constexpr (std::is_fundamental_v<T>)
2716
2809
  {
2717
- return Type<Pointer<T>>::verify();
2718
- return Type<Buffer<T>>::verify();
2719
- }
2720
- else
2721
- {
2722
- return Type<T>::verify();
2723
- }
2724
- }
2725
-
2726
- static VALUE rubyKlass()
2727
- {
2728
- if (Data_Type<std::shared_ptr<T>>::is_defined())
2729
- {
2730
- std::pair<VALUE, rb_data_type_t*> pair = Registries::instance.types.getType<std::shared_ptr<T>>();
2731
- return pair.first;
2732
- }
2733
- else
2734
- {
2735
- TypeMapper<T> typeMapper;
2736
- return typeMapper.rubyKlass();
2737
- }
2738
- }
2739
- };
2740
-
2741
- template <typename T>
2742
- class To_Ruby<std::shared_ptr<T>>
2743
- {
2744
- public:
2745
- To_Ruby() = default;
2746
-
2747
- explicit To_Ruby(Arg* arv)
2748
- {
2749
- }
2750
-
2751
- VALUE convert(std::shared_ptr<T>& data)
2752
- {
2753
- if constexpr (std::is_fundamental_v<T>)
2754
- {
2755
- return detail::wrap<std::shared_ptr<T>>(Data_Type<Pointer<T>>::klass(), Data_Type<Pointer<T>>::ruby_data_type(), data, true);
2810
+ result = result && Type<Pointer<T>>::verify();
2756
2811
  }
2757
2812
  else
2758
2813
  {
2759
- return detail::wrap<std::shared_ptr<T>>(Data_Type<T>::klass(), Data_Type<T>::ruby_data_type(), data, true);
2814
+ result = result && Type<T>::verify();
2760
2815
  }
2761
- }
2762
-
2763
- VALUE convert(std::shared_ptr<T>&& data)
2764
- {
2765
- if constexpr (std::is_fundamental_v<T>)
2766
- {
2767
- return detail::wrap<std::shared_ptr<T>>(Data_Type<Pointer<T>>::klass(), Data_Type<Pointer<T>>::ruby_data_type(), data, true);
2768
- }
2769
- else
2770
- {
2771
- return detail::wrap<std::shared_ptr<T>>(Data_Type<T>::klass(), Data_Type<T>::ruby_data_type(), data, true);
2772
- }
2773
- }
2774
- };
2775
-
2776
- template <typename T>
2777
- class From_Ruby<std::shared_ptr<T>>
2778
- {
2779
- public:
2780
- From_Ruby() = default;
2781
-
2782
- explicit From_Ruby(Arg * arg) : arg_(arg)
2783
- {
2784
- }
2785
-
2786
- Convertible is_convertible(VALUE value)
2787
- {
2788
- switch (rb_type(value))
2789
- {
2790
- case RUBY_T_DATA:
2791
- return Convertible::Exact;
2792
- break;
2793
- default:
2794
- return Convertible::None;
2795
- }
2796
- }
2797
-
2798
- std::shared_ptr<T> convert(VALUE value)
2799
- {
2800
- // Get the wrapper
2801
- WrapperBase* wrapperBase = detail::getWrapper(value);
2802
-
2803
- // Was this shared_ptr created by the user from Ruby? If so it will
2804
- // be wrapped as a pointer, std::shared_ptr<T>*. In the case just
2805
- // return the shared pointer
2806
- if (dynamic_cast<Wrapper<std::shared_ptr<T>*>*>(wrapperBase))
2807
- {
2808
- // Use unwrap to validate the underlying wrapper is the correct type
2809
- std::shared_ptr<T>* ptr = unwrap<std::shared_ptr<T>>(value, Data_Type<std::shared_ptr<T>>::ruby_data_type(), false);
2810
- return *ptr;
2811
- }
2812
- else if (std::is_fundamental_v<T>)
2813
- {
2814
- // Get the wrapper again to validate T's type
2815
- Wrapper<std::shared_ptr<T>>* wrapper = getWrapper<Wrapper<std::shared_ptr<T>>>(value, Data_Type<Pointer<T>>::ruby_data_type());
2816
- return wrapper->data();
2817
- }
2818
- else
2819
- {
2820
- // Get the wrapper again to validate T's type
2821
- Wrapper<std::shared_ptr<T>>* wrapper = getWrapper<Wrapper<std::shared_ptr<T>>>(value, Data_Type<T>::ruby_data_type());
2822
- return wrapper->data();
2823
- }
2824
- }
2825
- private:
2826
- Arg* arg_ = nullptr;
2827
- };
2828
-
2829
- template <typename T>
2830
- class To_Ruby<std::shared_ptr<T>&>
2831
- {
2832
- public:
2833
- To_Ruby() = default;
2834
-
2835
- explicit To_Ruby(Arg* arg)
2836
- {
2837
- }
2838
-
2839
- VALUE convert(std::shared_ptr<T>& data)
2840
- {
2841
- return detail::wrap(Data_Type<T>::klass(), Data_Type<T>::ruby_data_type(), data, true);
2842
- }
2843
- };
2844
-
2845
- template <typename T>
2846
- class From_Ruby<std::shared_ptr<T>&>
2847
- {
2848
- public:
2849
- From_Ruby() = default;
2850
2816
 
2851
- explicit From_Ruby(Arg * arg) : arg_(arg)
2852
- {
2853
- }
2854
-
2855
- Convertible is_convertible(VALUE value)
2856
- {
2857
- switch (rb_type(value))
2817
+ if (result)
2858
2818
  {
2859
- case RUBY_T_DATA:
2860
- return Convertible::Exact;
2861
- break;
2862
- default:
2863
- return Convertible::None;
2819
+ define_shared_ptr<T>();
2864
2820
  }
2865
- }
2866
2821
 
2867
- std::shared_ptr<T>& convert(VALUE value)
2868
- {
2869
- // Get the wrapper
2870
- WrapperBase* wrapperBase = detail::getWrapper(value);
2871
-
2872
- // Was this shared_ptr created by the user from Ruby? If so it will
2873
- // be wrapped as a pointer, std::shared_ptr<T>*. In the case just
2874
- // return the shared pointer
2875
- if (dynamic_cast<Wrapper<std::shared_ptr<T>*>*>(wrapperBase))
2876
- {
2877
- // Use unwrap to validate the underlying wrapper is the correct type
2878
- std::shared_ptr<T>* ptr = unwrap<std::shared_ptr<T>>(value, Data_Type<std::shared_ptr<T>>::ruby_data_type(), false);
2879
- return *ptr;
2880
- }
2881
- else if (std::is_fundamental_v<T>)
2882
- {
2883
- // Get the wrapper again to validate T's type
2884
- Wrapper<std::shared_ptr<T>>* wrapper = getWrapper<Wrapper<std::shared_ptr<T>>>(value, Data_Type<Pointer<T>>::ruby_data_type());
2885
- return wrapper->data();
2886
- }
2887
- else
2888
- {
2889
- // Get the wrapper again to validate T's type
2890
- Wrapper<std::shared_ptr<T>>* wrapper = getWrapper<Wrapper<std::shared_ptr<T>>>(value, Data_Type<T>::ruby_data_type());
2891
- return wrapper->data();
2892
- }
2822
+ return result;
2893
2823
  }
2894
-
2895
- private:
2896
- Arg* arg_ = nullptr;
2897
2824
  };
2898
2825
  }
2899
2826
 
@@ -2912,7 +2839,7 @@ namespace Rice::detail
2912
2839
  using Tuple_T = std::tuple<Types...>;
2913
2840
 
2914
2841
  template<std::size_t... I>
2915
- constexpr static bool verifyTypes(std::index_sequence<I...>& indices)
2842
+ constexpr static bool verifyTypes(std::index_sequence<I...>&)
2916
2843
  {
2917
2844
  return (Type<std::tuple_element_t<I, Tuple_T>>::verify() && ...);
2918
2845
  }
@@ -2936,7 +2863,7 @@ namespace Rice::detail
2936
2863
  public:
2937
2864
  To_Ruby() = default;
2938
2865
 
2939
- explicit To_Ruby(Return* returnInfo) : returnInfo_(returnInfo)
2866
+ explicit To_Ruby(Arg* arg) : arg_(arg)
2940
2867
  {
2941
2868
  }
2942
2869
 
@@ -2953,7 +2880,7 @@ namespace Rice::detail
2953
2880
  }
2954
2881
 
2955
2882
  private:
2956
- Return* returnInfo_ = nullptr;
2883
+ Arg* arg_ = nullptr;
2957
2884
  };
2958
2885
 
2959
2886
  template<typename...Types>
@@ -2962,7 +2889,7 @@ namespace Rice::detail
2962
2889
  public:
2963
2890
  To_Ruby() = default;
2964
2891
 
2965
- explicit To_Ruby(Return* returnInfo) : returnInfo_(returnInfo)
2892
+ explicit To_Ruby(Arg* arg) : arg_(arg)
2966
2893
  {
2967
2894
  }
2968
2895
 
@@ -2970,7 +2897,7 @@ namespace Rice::detail
2970
2897
  {
2971
2898
  Array result;
2972
2899
 
2973
- bool isOwner = (this->returnInfo_ && this->returnInfo_->isOwner());
2900
+ bool isOwner = (this->arg_ && this->arg_->isOwner());
2974
2901
 
2975
2902
  for_each_tuple(data, [&](auto& element)
2976
2903
  {
@@ -2981,7 +2908,7 @@ namespace Rice::detail
2981
2908
  }
2982
2909
 
2983
2910
  private:
2984
- Return* returnInfo_ = nullptr;
2911
+ Arg* arg_ = nullptr;
2985
2912
  };
2986
2913
 
2987
2914
  template<typename...Types>
@@ -2990,35 +2917,28 @@ namespace Rice::detail
2990
2917
  public:
2991
2918
  using Tuple_T = std::tuple<Types...>;
2992
2919
 
2993
- template<std::size_t... I>
2994
- constexpr static bool verifyTypes(Array& array, std::index_sequence<I...>& indices)
2995
- {
2996
- return (Type<std::tuple_element_t<I, Tuple_T>>::verify() && ...);
2997
- }
2998
-
2999
2920
  From_Ruby() = default;
3000
2921
 
3001
- explicit From_Ruby(Arg* arg)
2922
+ explicit From_Ruby(Arg* arg) : arg_(arg)
3002
2923
  {
3003
2924
  }
3004
2925
 
3005
- Convertible is_convertible(VALUE value)
2926
+ double is_convertible(VALUE value)
3006
2927
  {
3007
- Convertible result = Convertible::None;
3008
-
3009
2928
  // The ruby value must be an array of the correct size
3010
2929
  if (rb_type(value) != RUBY_T_ARRAY || Array(value).size() != std::tuple_size_v<Tuple_T>)
3011
2930
  {
3012
- return result;
2931
+ return Convertible::None;
3013
2932
  }
3014
-
3015
- // Now check that each tuple type is convertible
2933
+
2934
+ // Now check that each tuple type is convertible - use minimum score
2935
+ double result = Convertible::Exact;
3016
2936
  Array array(value);
3017
2937
  int i = 0;
3018
2938
  for_each_tuple(this->fromRubys_,
3019
2939
  [&](auto& fromRuby)
3020
2940
  {
3021
- result = result | fromRuby.is_convertible(array[i].value());
2941
+ result = (std::min)(result, fromRuby.is_convertible(array[i].value()));
3022
2942
  i++;
3023
2943
  });
3024
2944
 
@@ -3026,7 +2946,7 @@ namespace Rice::detail
3026
2946
  }
3027
2947
 
3028
2948
  template <std::size_t... I>
3029
- std::tuple<Types...> convertInternal(Array array, std::index_sequence<I...>& indices)
2949
+ std::tuple<Types...> convertInternal(Array array, std::index_sequence<I...>&)
3030
2950
  {
3031
2951
  return std::forward_as_tuple(std::get<I>(this->fromRubys_).convert(array[I].value())...);
3032
2952
  }
@@ -3039,25 +2959,11 @@ namespace Rice::detail
3039
2959
  }
3040
2960
 
3041
2961
  private:
2962
+ Arg* arg_ = nullptr;
3042
2963
  // Possible converters we could use for this variant
3043
2964
  using From_Ruby_Ts = std::tuple<From_Ruby<Types>...>;
3044
2965
  From_Ruby_Ts fromRubys_;
3045
2966
  };
3046
-
3047
- /* template<typename...Types>
3048
- class From_Ruby<std::tuple<Types...>&> : public From_Ruby<std::tuple<Types...>>
3049
- {
3050
- public:
3051
- std::tuple<Types...>& convert(VALUE value)
3052
- {
3053
- int index = this->figureIndex(value);
3054
- this->converted_ = this->convertInternal(value, index);
3055
- return this->converted_;
3056
- }
3057
-
3058
- private:
3059
- std::tuple<Types...> converted_;
3060
- };*/
3061
2967
  }
3062
2968
 
3063
2969
 
@@ -3146,7 +3052,7 @@ namespace Rice::detail
3146
3052
  using Tuple_T = std::tuple<Types...>;
3147
3053
 
3148
3054
  template<std::size_t... I>
3149
- constexpr static bool verifyTypes(std::index_sequence<I...>& indices)
3055
+ constexpr static bool verifyTypes(std::index_sequence<I...>&)
3150
3056
  {
3151
3057
  return (Type<std::tuple_element_t<I, Tuple_T>>::verify() && ...);
3152
3058
  }
@@ -3170,18 +3076,23 @@ namespace Rice::detail
3170
3076
  public:
3171
3077
  To_Ruby() = default;
3172
3078
 
3173
- explicit To_Ruby(Return* returnInfo) : returnInfo_(returnInfo)
3079
+ explicit To_Ruby(Arg* arg) : arg_(arg)
3174
3080
  {
3175
3081
  }
3176
3082
 
3177
3083
  template<typename U, typename V>
3178
3084
  VALUE convertElement(U& data, bool takeOwnership)
3179
3085
  {
3180
- return To_Ruby<V>().convert(std::forward<V>(std::get<V>(data)));
3086
+ Arg arg("arg1");
3087
+ if (takeOwnership)
3088
+ {
3089
+ arg.takeOwnership();
3090
+ }
3091
+ return To_Ruby<V>(&arg).convert(std::forward<V>(std::get<V>(data)));
3181
3092
  }
3182
3093
 
3183
3094
  template<typename U, std::size_t... I>
3184
- VALUE convertIterator(U& data, bool takeOwnership, std::index_sequence<I...>& indices)
3095
+ VALUE convertIterator(U& data, bool takeOwnership, std::index_sequence<I...>&)
3185
3096
  {
3186
3097
  // Create a tuple of the variant types so we can look over the tuple's types
3187
3098
  using Tuple_T = std::tuple<Types...>;
@@ -3239,7 +3150,7 @@ namespace Rice::detail
3239
3150
  }
3240
3151
 
3241
3152
  private:
3242
- Return* returnInfo_ = nullptr;
3153
+ Arg* arg_ = nullptr;
3243
3154
  };
3244
3155
 
3245
3156
  template<typename...Types>
@@ -3248,25 +3159,31 @@ namespace Rice::detail
3248
3159
  public:
3249
3160
  To_Ruby() = default;
3250
3161
 
3251
- explicit To_Ruby(Return* returnInfo) : returnInfo_(returnInfo)
3162
+ explicit To_Ruby(Arg* arg) : arg_(arg)
3252
3163
  {
3253
3164
  }
3254
3165
 
3255
3166
  template<typename U, typename V>
3256
3167
  VALUE convertElement(U& data, bool takeOwnership)
3257
3168
  {
3169
+ Arg arg("arg1");
3170
+ if (takeOwnership)
3171
+ {
3172
+ arg.takeOwnership();
3173
+ }
3174
+
3258
3175
  if constexpr (std::is_const_v<U>)
3259
3176
  {
3260
- return To_Ruby<V>().convert(std::get<V>(data));
3177
+ return To_Ruby<V>(&arg).convert(std::get<V>(data));
3261
3178
  }
3262
3179
  else
3263
3180
  {
3264
- return To_Ruby<V>().convert(std::forward<V>(std::get<V>(data)));
3181
+ return To_Ruby<V>(&arg).convert(std::forward<V>(std::get<V>(data)));
3265
3182
  }
3266
3183
  }
3267
3184
 
3268
3185
  template<typename U, std::size_t... I>
3269
- VALUE convertIterator(U& data, bool takeOwnership, std::index_sequence<I...>& indices)
3186
+ VALUE convertIterator(U& data, bool takeOwnership, std::index_sequence<I...>&)
3270
3187
  {
3271
3188
  // Create a tuple of the variant types so we can look over the tuple's types
3272
3189
  using Tuple_T = std::tuple<Types...>;
@@ -3292,13 +3209,13 @@ namespace Rice::detail
3292
3209
  template<typename U>
3293
3210
  VALUE convert(U& data)
3294
3211
  {
3295
- bool isOwner = (this->returnInfo_ && this->returnInfo_->isOwner());
3212
+ bool isOwner = (this->arg_ && this->arg_->isOwner());
3296
3213
  auto indices = std::make_index_sequence<std::variant_size_v<std::variant<Types...>>>{};
3297
3214
  return convertIterator(data, isOwner, indices);
3298
3215
  }
3299
3216
 
3300
3217
  private:
3301
- Return* returnInfo_ = nullptr;
3218
+ Arg* arg_ = nullptr;
3302
3219
  };
3303
3220
 
3304
3221
  template<typename...Types>
@@ -3307,18 +3224,18 @@ namespace Rice::detail
3307
3224
  public:
3308
3225
  From_Ruby() = default;
3309
3226
 
3310
- explicit From_Ruby(Arg* arg)
3227
+ explicit From_Ruby(Arg* arg) : arg_(arg)
3311
3228
  {
3312
3229
  }
3313
3230
 
3314
- Convertible is_convertible(VALUE value)
3231
+ double is_convertible(VALUE value)
3315
3232
  {
3316
- Convertible result = Convertible::None;
3233
+ double result = Convertible::None;
3317
3234
 
3318
3235
  for_each_tuple(this->fromRubys_,
3319
3236
  [&](auto& fromRuby)
3320
3237
  {
3321
- result = result | fromRuby.is_convertible(value);
3238
+ result = (std::max)(result, fromRuby.is_convertible(value));
3322
3239
  });
3323
3240
 
3324
3241
  return result;
@@ -3330,17 +3247,17 @@ namespace Rice::detail
3330
3247
  {
3331
3248
  int i = 0;
3332
3249
  int index = -1;
3333
- Convertible foundConversion = Convertible::None;
3250
+ double foundScore = Convertible::None;
3334
3251
 
3335
3252
  for_each_tuple(this->fromRubys_,
3336
3253
  [&](auto& fromRuby)
3337
3254
  {
3338
- Convertible isConvertible = fromRuby.is_convertible(value);
3255
+ double score = fromRuby.is_convertible(value);
3339
3256
 
3340
- if (isConvertible > foundConversion)
3257
+ if (score > foundScore)
3341
3258
  {
3342
3259
  index = i;
3343
- foundConversion = isConvertible;
3260
+ foundScore = score;
3344
3261
  }
3345
3262
  i++;
3346
3263
  });
@@ -3378,7 +3295,10 @@ namespace Rice::detail
3378
3295
  return convertInternal<I + 1>(value, index);
3379
3296
  }
3380
3297
  }
3381
- rb_raise(rb_eArgError, "Could not find converter for variant");
3298
+ else
3299
+ {
3300
+ rb_raise(rb_eArgError, "Could not find converter for variant");
3301
+ }
3382
3302
  }
3383
3303
 
3384
3304
  std::variant<Types...> convert(VALUE value)
@@ -3388,6 +3308,7 @@ namespace Rice::detail
3388
3308
  }
3389
3309
 
3390
3310
  private:
3311
+ Arg* arg_ = nullptr;
3391
3312
  // Possible converters we could use for this variant
3392
3313
  using From_Ruby_Ts = std::tuple<From_Ruby<Types>...>;
3393
3314
  From_Ruby_Ts fromRubys_;
@@ -3399,7 +3320,7 @@ namespace Rice::detail
3399
3320
  public:
3400
3321
  From_Ruby() = default;
3401
3322
 
3402
- explicit From_Ruby(Arg* arg)
3323
+ explicit From_Ruby(Arg* arg) : arg_(arg)
3403
3324
  {
3404
3325
  }
3405
3326
 
@@ -3411,6 +3332,7 @@ namespace Rice::detail
3411
3332
  }
3412
3333
 
3413
3334
  private:
3335
+ Arg* arg_ = nullptr;
3414
3336
  std::variant<Types...> converted_;
3415
3337
  };
3416
3338
  }
@@ -3418,19 +3340,25 @@ namespace Rice::detail
3418
3340
 
3419
3341
  // ========= unique_ptr.hpp =========
3420
3342
 
3343
+ namespace Rice
3344
+ {
3345
+ template<typename T>
3346
+ Data_Type<std::unique_ptr<T>> define_unique_ptr(std::string klassName = "");
3347
+ }
3348
+
3421
3349
  namespace Rice::detail
3422
3350
  {
3423
3351
  template<typename T>
3424
3352
  class Wrapper<std::unique_ptr<T>> : public WrapperBase
3425
3353
  {
3426
3354
  public:
3427
- Wrapper(std::unique_ptr<T>&& data);
3355
+ Wrapper(rb_data_type_t* rb_data_type, std::unique_ptr<T>&& data);
3428
3356
  ~Wrapper();
3429
- void* get() override;
3430
- std::unique_ptr<T>& data();
3357
+ void* get(rb_data_type_t* requestedType) override;
3431
3358
 
3432
3359
  private:
3433
3360
  std::unique_ptr<T> data_;
3361
+ rb_data_type_t* inner_rb_data_type_;
3434
3362
  };
3435
3363
  }
3436
3364
 
@@ -3438,142 +3366,132 @@ namespace Rice::detail
3438
3366
  // --------- unique_ptr.ipp ---------
3439
3367
  #include <memory>
3440
3368
 
3441
- namespace Rice::detail
3369
+ namespace Rice
3442
3370
  {
3443
3371
  template<typename T>
3444
- inline Wrapper<std::unique_ptr<T>>::Wrapper(std::unique_ptr<T>&& data)
3445
- : data_(std::move(data))
3446
- {
3447
- }
3448
-
3449
- template<typename T>
3450
- inline Wrapper<std::unique_ptr<T>>::~Wrapper()
3372
+ Data_Type<std::unique_ptr<T>> define_unique_ptr(std::string klassName)
3451
3373
  {
3452
- Registries::instance.instances.remove(this->get());
3453
- }
3374
+ using UniquePtr_T = std::unique_ptr<T>;
3375
+ using Data_Type_T = Data_Type<UniquePtr_T>;
3454
3376
 
3455
- template<typename T>
3456
- inline void* Wrapper<std::unique_ptr<T>>::get()
3457
- {
3458
- return (void*)this->data_.get();
3459
- }
3460
-
3461
- template<typename T>
3462
- inline std::unique_ptr<T>& Wrapper<std::unique_ptr<T>>::data()
3463
- {
3464
- return data_;
3465
- }
3466
-
3467
- template <typename T>
3468
- class To_Ruby<std::unique_ptr<T>>
3469
- {
3470
- public:
3471
- To_Ruby() = default;
3472
-
3473
- explicit To_Ruby(Return* returnInfo) : returnInfo_(returnInfo)
3377
+ if (klassName.empty())
3474
3378
  {
3379
+ detail::TypeMapper<UniquePtr_T> typeMapper;
3380
+ klassName = typeMapper.rubyName();
3475
3381
  }
3476
3382
 
3477
- VALUE convert(std::unique_ptr<T>& data)
3383
+ Module rb_mStd = define_module("Std");
3384
+ if (Data_Type_T::check_defined(klassName, rb_mStd))
3478
3385
  {
3479
- std::pair<VALUE, rb_data_type_t*> rubyTypeInfo = detail::Registries::instance.types.figureType<T>(*data);
3480
- return detail::wrap<std::unique_ptr<T>>(rubyTypeInfo.first, rubyTypeInfo.second, data, true);
3386
+ return Data_Type_T();
3481
3387
  }
3482
3388
 
3483
- VALUE convert(std::unique_ptr<T>&& data)
3389
+ Identifier id(klassName);
3390
+ Data_Type_T result = define_class_under<detail::intrinsic_type<UniquePtr_T>>(rb_mStd, id).
3391
+ define_method("get", &UniquePtr_T::get).
3392
+ define_method("release", &UniquePtr_T::release).
3393
+ define_method("reset", &UniquePtr_T::reset).
3394
+ define_method("swap", &UniquePtr_T::swap).
3395
+ define_method("empty?", [](UniquePtr_T& self)->bool
3396
+ {
3397
+ return !self;
3398
+ });
3399
+
3400
+ // Setup delegation to forward T's methods via get (only for non-fundamental, non-void types)
3401
+ if constexpr (!std::is_void_v<T> && !std::is_fundamental_v<T>)
3484
3402
  {
3485
- std::pair<VALUE, rb_data_type_t*> rubyTypeInfo = detail::Registries::instance.types.figureType<T>(*data);
3486
- return detail::wrap<std::unique_ptr<T>>(rubyTypeInfo.first, rubyTypeInfo.second, data, true);
3403
+ detail::define_forwarding(result.klass(), Data_Type<T>::klass());
3487
3404
  }
3488
3405
 
3489
- private:
3490
- Return* returnInfo_ = nullptr;
3491
- };
3406
+ return result;
3407
+ }
3408
+ }
3492
3409
 
3493
- template <typename T>
3494
- class To_Ruby<std::unique_ptr<T>&>
3410
+ // --------- Wrapper ---------
3411
+ namespace Rice::detail
3412
+ {
3413
+ template<typename T>
3414
+ Wrapper<std::unique_ptr<T>>::Wrapper(rb_data_type_t* rb_data_type, std::unique_ptr<T>&& data)
3415
+ : WrapperBase(rb_data_type), data_(std::move(data))
3495
3416
  {
3496
- public:
3497
- To_Ruby() = default;
3417
+ using Intrinsic_T = intrinsic_type<T>;
3498
3418
 
3499
- explicit To_Ruby(Return* returnInfo) : returnInfo_(returnInfo)
3419
+ if constexpr (std::is_fundamental_v<Intrinsic_T>)
3500
3420
  {
3421
+ inner_rb_data_type_ = Data_Type<Pointer<Intrinsic_T>>::ruby_data_type();
3501
3422
  }
3502
-
3503
- VALUE convert(std::unique_ptr<T>& data)
3423
+ else
3504
3424
  {
3505
- std::pair<VALUE, rb_data_type_t*> rubyTypeInfo = detail::Registries::instance.types.figureType<T>(*data);
3506
- return detail::wrap<std::unique_ptr<T>>(rubyTypeInfo.first, rubyTypeInfo.second, data, true);
3425
+ inner_rb_data_type_ = Data_Type<Intrinsic_T>::ruby_data_type();
3507
3426
  }
3427
+ }
3508
3428
 
3509
- private:
3510
- Return* returnInfo_ = nullptr;
3511
- };
3429
+ template<typename T>
3430
+ Wrapper<std::unique_ptr<T>>::~Wrapper()
3431
+ {
3432
+ Registries::instance.instances.remove(this->get(this->rb_data_type_));
3433
+ }
3512
3434
 
3513
- template <typename T>
3514
- class From_Ruby<std::unique_ptr<T>>
3435
+ template<typename T>
3436
+ void* Wrapper<std::unique_ptr<T>>::get(rb_data_type_t* requestedType)
3515
3437
  {
3516
- public:
3517
- Wrapper<std::unique_ptr<T>>* is_same_smart_ptr(VALUE value)
3438
+ if (rb_typeddata_inherited_p(this->rb_data_type_, requestedType))
3518
3439
  {
3519
- WrapperBase* wrapper = detail::getWrapper(value, Data_Type<T>::ruby_data_type());
3520
- return dynamic_cast<Wrapper<std::unique_ptr<T>>*>(wrapper);
3440
+ return &this->data_;
3521
3441
  }
3522
-
3523
- From_Ruby() = default;
3524
-
3525
- explicit From_Ruby(Arg* arg)
3442
+ else if (rb_typeddata_inherited_p(this->inner_rb_data_type_, requestedType))
3526
3443
  {
3444
+ return this->data_.get();
3527
3445
  }
3528
-
3529
- Convertible is_convertible(VALUE value)
3446
+ else
3530
3447
  {
3531
- if (!is_same_smart_ptr(value))
3532
- return Convertible::None;
3448
+ throw Exception(rb_eTypeError, "wrong argument type (expected %s)",
3449
+ requestedType->wrap_struct_name);
3450
+ }
3451
+ }
3533
3452
 
3534
- switch (rb_type(value))
3453
+ }
3454
+
3455
+ // --------- Type ---------
3456
+ namespace Rice::detail
3457
+ {
3458
+ template<typename T>
3459
+ struct Type<std::unique_ptr<T>>
3460
+ {
3461
+ static bool verify()
3462
+ {
3463
+ bool result = true;
3464
+ if constexpr (std::is_fundamental_v<T>)
3535
3465
  {
3536
- case RUBY_T_DATA:
3537
- return Convertible::Exact;
3538
- break;
3539
- default:
3540
- return Convertible::None;
3466
+ result = result && Type<Pointer<T>>::verify();
3467
+ }
3468
+ else
3469
+ {
3470
+ result = result && Type<T>::verify();
3541
3471
  }
3542
- }
3543
3472
 
3544
- std::unique_ptr<T> convert(VALUE value)
3545
- {
3546
- Wrapper<std::unique_ptr<T>>* wrapper = is_same_smart_ptr(value);
3547
- if (!wrapper)
3473
+ if (result)
3548
3474
  {
3549
- std::string message = "Invalid smart pointer wrapper";
3550
- throw std::runtime_error(message.c_str());
3475
+ define_unique_ptr<T>();
3551
3476
  }
3552
- return std::move(wrapper->data());
3477
+
3478
+ return result;
3553
3479
  }
3554
3480
  };
3555
3481
 
3482
+ // --------- From_Ruby ---------
3556
3483
  template <typename T>
3557
- class From_Ruby<std::unique_ptr<T>&>
3484
+ class From_Ruby<std::unique_ptr<T>>
3558
3485
  {
3559
3486
  public:
3560
- Wrapper<std::unique_ptr<T>>* is_same_smart_ptr(VALUE value)
3561
- {
3562
- WrapperBase* wrapper = detail::getWrapper(value, Data_Type<T>::ruby_data_type());
3563
- return dynamic_cast<Wrapper<std::unique_ptr<T>>*>(wrapper);
3564
- }
3565
-
3566
3487
  From_Ruby() = default;
3567
3488
 
3568
- explicit From_Ruby(Arg* arg)
3489
+ explicit From_Ruby(Arg* arg) : arg_(arg)
3569
3490
  {
3570
3491
  }
3571
3492
 
3572
- Convertible is_convertible(VALUE value)
3493
+ double is_convertible(VALUE value)
3573
3494
  {
3574
- if (!is_same_smart_ptr(value))
3575
- return Convertible::None;
3576
-
3577
3495
  switch (rb_type(value))
3578
3496
  {
3579
3497
  case RUBY_T_DATA:
@@ -3584,39 +3502,15 @@ namespace Rice::detail
3584
3502
  }
3585
3503
  }
3586
3504
 
3587
- std::unique_ptr<T>& convert(VALUE value)
3588
- {
3589
- Wrapper<std::unique_ptr<T>>* wrapper = is_same_smart_ptr(value);
3590
- if (!wrapper)
3591
- {
3592
- std::string message = "Invalid smart pointer wrapper";
3593
- throw std::runtime_error(message.c_str());
3594
- }
3595
- return wrapper->data();
3596
- }
3597
- };
3598
-
3599
- template<typename T>
3600
- struct Type<std::unique_ptr<T>>
3601
- {
3602
- static bool verify()
3505
+ std::unique_ptr<T> convert(VALUE value)
3603
3506
  {
3604
- if constexpr (std::is_fundamental_v<T>)
3605
- {
3606
- return Type<Pointer<T>>::verify();
3607
- return Type<Buffer<T>>::verify();
3608
- }
3609
- else
3610
- {
3611
- return Type<T>::verify();
3612
- }
3507
+ std::unique_ptr<T>* result = detail::unwrap<std::unique_ptr<T>>(value, Data_Type<std::unique_ptr<T>>::ruby_data_type(), this->arg_ && this->arg_->isOwner());
3508
+ // The reason we need this overriden From_Ruby is to do this std::move.
3509
+ return std::move(*result);
3613
3510
  }
3614
3511
 
3615
- static VALUE rubyKlass()
3616
- {
3617
- TypeMapper<T> typeMapper;
3618
- return typeMapper.rubyKlass();
3619
- }
3512
+ private:
3513
+ Arg* arg_ = nullptr;
3620
3514
  };
3621
3515
  }
3622
3516
 
@@ -3740,7 +3634,11 @@ namespace Rice
3740
3634
  {
3741
3635
  if constexpr (detail::is_comparable_v<Mapped_T>)
3742
3636
  {
3743
- klass_.define_method("value?", [](T& unordered_map, Mapped_T& value) -> bool
3637
+ klass_.define_method("==", [](T& unordered_map, T& other)->bool
3638
+ {
3639
+ return unordered_map == other;
3640
+ })
3641
+ .define_method("value?", [](T& unordered_map, Mapped_T& value) -> bool
3744
3642
  {
3745
3643
  auto it = std::find_if(unordered_map.begin(), unordered_map.end(),
3746
3644
  [&value](auto& pair)
@@ -3750,10 +3648,11 @@ namespace Rice
3750
3648
 
3751
3649
  return it != unordered_map.end();
3752
3650
  });
3651
+ rb_define_alias(klass_, "eql?", "==");
3753
3652
  }
3754
3653
  else
3755
3654
  {
3756
- klass_.define_method("value?", [](T& unordered_map, Mapped_T& value) -> bool
3655
+ klass_.define_method("value?", [](T&, Mapped_T&) -> bool
3757
3656
  {
3758
3657
  return false;
3759
3658
  });
@@ -3838,10 +3737,10 @@ namespace Rice
3838
3737
  }
3839
3738
  else
3840
3739
  {
3841
- klass_.define_method("to_s", [](const T& unordered_map)
3842
- {
3843
- return "[Not printable]";
3844
- });
3740
+ klass_.define_method("to_s", [](const T&)
3741
+ {
3742
+ return "[Not printable]";
3743
+ });
3845
3744
  }
3846
3745
  }
3847
3746
 
@@ -3932,7 +3831,7 @@ namespace Rice
3932
3831
  {
3933
3832
  }
3934
3833
 
3935
- Convertible is_convertible(VALUE value)
3834
+ double is_convertible(VALUE value)
3936
3835
  {
3937
3836
  switch (rb_type(value))
3938
3837
  {
@@ -3940,7 +3839,7 @@ namespace Rice
3940
3839
  return Data_Type<std::unordered_map<T, U>>::is_descendant(value) ? Convertible::Exact : Convertible::None;
3941
3840
  break;
3942
3841
  case RUBY_T_HASH:
3943
- return Convertible::Cast;
3842
+ return Convertible::Exact;
3944
3843
  break;
3945
3844
  default:
3946
3845
  return Convertible::None;
@@ -3966,7 +3865,7 @@ namespace Rice
3966
3865
  }
3967
3866
  default:
3968
3867
  {
3969
- throw Exception(rb_eTypeError, "wrong argument type %s (expected % s)",
3868
+ throw Exception(rb_eTypeError, "wrong argument type %s (expected %s)",
3970
3869
  detail::protect(rb_obj_classname, value), "std::unordered_map");
3971
3870
  }
3972
3871
  }
@@ -3986,7 +3885,7 @@ namespace Rice
3986
3885
  {
3987
3886
  }
3988
3887
 
3989
- Convertible is_convertible(VALUE value)
3888
+ double is_convertible(VALUE value)
3990
3889
  {
3991
3890
  switch (rb_type(value))
3992
3891
  {
@@ -3994,7 +3893,7 @@ namespace Rice
3994
3893
  return Data_Type<std::unordered_map<T, U>>::is_descendant(value) ? Convertible::Exact : Convertible::None;
3995
3894
  break;
3996
3895
  case RUBY_T_HASH:
3997
- return Convertible::Cast;
3896
+ return Convertible::Exact;
3998
3897
  break;
3999
3898
  default:
4000
3899
  return Convertible::None;
@@ -4021,7 +3920,7 @@ namespace Rice
4021
3920
  }
4022
3921
  default:
4023
3922
  {
4024
- throw Exception(rb_eTypeError, "wrong argument type %s (expected % s)",
3923
+ throw Exception(rb_eTypeError, "wrong argument type %s (expected %s)",
4025
3924
  detail::protect(rb_obj_classname, value), "std::unordered_map");
4026
3925
  }
4027
3926
  }
@@ -4042,7 +3941,7 @@ namespace Rice
4042
3941
  {
4043
3942
  }
4044
3943
 
4045
- Convertible is_convertible(VALUE value)
3944
+ double is_convertible(VALUE value)
4046
3945
  {
4047
3946
  switch (rb_type(value))
4048
3947
  {
@@ -4053,7 +3952,7 @@ namespace Rice
4053
3952
  return Convertible::Exact;
4054
3953
  break;
4055
3954
  case RUBY_T_HASH:
4056
- return Convertible::Cast;
3955
+ return Convertible::Exact;
4057
3956
  break;
4058
3957
  default:
4059
3958
  return Convertible::None;
@@ -4080,7 +3979,7 @@ namespace Rice
4080
3979
  }
4081
3980
  default:
4082
3981
  {
4083
- throw Exception(rb_eTypeError, "wrong argument type %s (expected % s)",
3982
+ throw Exception(rb_eTypeError, "wrong argument type %s (expected %s)",
4084
3983
  detail::protect(rb_obj_classname, value), "std::unordered_map");
4085
3984
  }
4086
3985
  }
@@ -4144,7 +4043,7 @@ namespace Rice
4144
4043
  Difference_T normalizeIndex(Size_T size, Difference_T index, bool enforceBounds = false)
4145
4044
  {
4146
4045
  // Negative indices mean count from the right
4147
- if (index < 0 && (-index <= size))
4046
+ if (index < 0 && ((Size_T)(-index) <= size))
4148
4047
  {
4149
4048
  index = size + index;
4150
4049
  }
@@ -4188,7 +4087,7 @@ namespace Rice
4188
4087
  }
4189
4088
 
4190
4089
  // Wrap the vector
4191
- detail::wrapConstructed<T>(self, Data_Type<T>::ruby_data_type(), data, true);
4090
+ detail::wrapConstructed<T>(self, Data_Type<T>::ruby_data_type(), data);
4192
4091
  });
4193
4092
  }
4194
4093
 
@@ -4204,10 +4103,10 @@ namespace Rice
4204
4103
  }
4205
4104
  else
4206
4105
  {
4207
- klass_.define_method("resize", [](const T& vector, Size_T newSize)
4208
- {
4209
- // Do nothing
4210
- });
4106
+ klass_.define_method("resize", [](const T&, Size_T)
4107
+ {
4108
+ // Do nothing
4109
+ });
4211
4110
  }
4212
4111
  }
4213
4112
 
@@ -4264,7 +4163,7 @@ namespace Rice
4264
4163
  return vector[index];
4265
4164
  }
4266
4165
  })
4267
- .template define_method<Value_T*(T::*)()>("data", &T::data, Return().setBuffer());
4166
+ .template define_method<Value_T*(T::*)()>("data", &T::data, ReturnBuffer());
4268
4167
  }
4269
4168
  else
4270
4169
  {
@@ -4345,7 +4244,11 @@ namespace Rice
4345
4244
  {
4346
4245
  if constexpr (detail::is_comparable_v<T>)
4347
4246
  {
4348
- klass_.define_method("delete", [](T& vector, Parameter_T element) -> std::optional<Value_T>
4247
+ klass_.define_method("==", [](T& vector, T& other)->bool
4248
+ {
4249
+ return vector == other;
4250
+ })
4251
+ .define_method("delete", [](T& vector, Parameter_T element) -> std::optional<Value_T>
4349
4252
  {
4350
4253
  auto iter = std::find(vector.begin(), vector.end(), element);
4351
4254
  if (iter == vector.end())
@@ -4379,21 +4282,22 @@ namespace Rice
4379
4282
  return iter - vector.begin();
4380
4283
  }
4381
4284
  });
4285
+ rb_define_alias(klass_, "eql?", "==");
4382
4286
  }
4383
4287
  else
4384
4288
  {
4385
- klass_.define_method("delete", [](T& vector, Parameter_T element) -> std::optional<Value_T>
4386
- {
4387
- return std::nullopt;
4388
- })
4389
- .define_method("include?", [](const T& vector, Parameter_T element)
4390
- {
4391
- return false;
4392
- })
4393
- .define_method("index", [](const T& vector, Parameter_T element) -> std::optional<Difference_T>
4394
- {
4395
- return std::nullopt;
4396
- });
4289
+ klass_.define_method("delete", [](T&, Parameter_T) -> std::optional<Value_T>
4290
+ {
4291
+ return std::nullopt;
4292
+ })
4293
+ .define_method("include?", [](const T&, Parameter_T)
4294
+ {
4295
+ return false;
4296
+ })
4297
+ .define_method("index", [](const T&, Parameter_T) -> std::optional<Difference_T>
4298
+ {
4299
+ return std::nullopt;
4300
+ });
4397
4301
  }
4398
4302
  }
4399
4303
 
@@ -4418,7 +4322,7 @@ namespace Rice
4418
4322
  })
4419
4323
  .define_method("insert", [this](T& vector, Difference_T index, Parameter_T element) -> T&
4420
4324
  {
4421
- int normalized = normalizeIndex(vector.size(), index, true);
4325
+ size_t normalized = normalizeIndex(vector.size(), index, true);
4422
4326
  // For a Ruby array a positive index means insert the element before the index. But
4423
4327
  // a negative index means insert the element *after* the index. std::vector
4424
4328
  // inserts *before* the index. So add 1 if this is a negative index.
@@ -4517,10 +4421,10 @@ namespace Rice
4517
4421
  }
4518
4422
  else
4519
4423
  {
4520
- klass_.define_method("to_s", [](const T& vector)
4521
- {
4522
- return "[Not printable]";
4523
- });
4424
+ klass_.define_method("to_s", [](const T&)
4425
+ {
4426
+ return "[Not printable]";
4427
+ });
4524
4428
  }
4525
4429
  }
4526
4430
 
@@ -4582,7 +4486,7 @@ namespace Rice
4582
4486
  {
4583
4487
  }
4584
4488
 
4585
- Convertible is_convertible(VALUE value)
4489
+ double is_convertible(VALUE value)
4586
4490
  {
4587
4491
  switch (rb_type(value))
4588
4492
  {
@@ -4592,7 +4496,7 @@ namespace Rice
4592
4496
  case RUBY_T_ARRAY:
4593
4497
  if constexpr (std::is_default_constructible_v<T>)
4594
4498
  {
4595
- return Convertible::Cast;
4499
+ return Convertible::Exact;
4596
4500
  }
4597
4501
  default:
4598
4502
  return Convertible::None;
@@ -4618,7 +4522,7 @@ namespace Rice
4618
4522
  }
4619
4523
  default:
4620
4524
  {
4621
- throw Exception(rb_eTypeError, "wrong argument type %s (expected % s)",
4525
+ throw Exception(rb_eTypeError, "wrong argument type %s (expected %s)",
4622
4526
  detail::protect(rb_obj_classname, value), "std::vector");
4623
4527
  }
4624
4528
  }
@@ -4638,7 +4542,7 @@ namespace Rice
4638
4542
  {
4639
4543
  }
4640
4544
 
4641
- Convertible is_convertible(VALUE value)
4545
+ double is_convertible(VALUE value)
4642
4546
  {
4643
4547
  switch (rb_type(value))
4644
4548
  {
@@ -4648,7 +4552,7 @@ namespace Rice
4648
4552
  case RUBY_T_ARRAY:
4649
4553
  if constexpr (std::is_default_constructible_v<T>)
4650
4554
  {
4651
- return Convertible::Cast;
4555
+ return Convertible::Exact;
4652
4556
  }
4653
4557
  default:
4654
4558
  return Convertible::None;
@@ -4675,7 +4579,7 @@ namespace Rice
4675
4579
  }
4676
4580
  default:
4677
4581
  {
4678
- throw Exception(rb_eTypeError, "wrong argument type %s (expected % s)",
4582
+ throw Exception(rb_eTypeError, "wrong argument type %s (expected %s)",
4679
4583
  detail::protect(rb_obj_classname, value), "std::vector");
4680
4584
  }
4681
4585
  }
@@ -4696,7 +4600,7 @@ namespace Rice
4696
4600
  {
4697
4601
  }
4698
4602
 
4699
- Convertible is_convertible(VALUE value)
4603
+ double is_convertible(VALUE value)
4700
4604
  {
4701
4605
  switch (rb_type(value))
4702
4606
  {
@@ -4709,7 +4613,7 @@ namespace Rice
4709
4613
  case RUBY_T_ARRAY:
4710
4614
  if constexpr (std::is_default_constructible_v<T>)
4711
4615
  {
4712
- return Convertible::Cast;
4616
+ return Convertible::Exact;
4713
4617
  }
4714
4618
  default:
4715
4619
  return Convertible::None;
@@ -4736,7 +4640,7 @@ namespace Rice
4736
4640
  }
4737
4641
  default:
4738
4642
  {
4739
- throw Exception(rb_eTypeError, "wrong argument type %s (expected % s)",
4643
+ throw Exception(rb_eTypeError, "wrong argument type %s (expected %s)",
4740
4644
  detail::protect(rb_obj_classname, value), "std::vector");
4741
4645
  }
4742
4646
  }
@@ -4757,7 +4661,7 @@ namespace Rice
4757
4661
  public:
4758
4662
  To_Ruby() = default;
4759
4663
 
4760
- explicit To_Ruby(Return* returnInfo) : returnInfo_(returnInfo)
4664
+ explicit To_Ruby(Arg* arg) : arg_(arg)
4761
4665
  {
4762
4666
  }
4763
4667
 
@@ -4767,7 +4671,7 @@ namespace Rice
4767
4671
  }
4768
4672
 
4769
4673
  private:
4770
- Return* returnInfo_ = nullptr;
4674
+ Arg* arg_ = nullptr;
4771
4675
  };
4772
4676
  }
4773
4677
  }