rice 4.3.0 → 4.3.1

Sign up to get free protection for your applications and to get access to all the features.
data/rice/Data_Object.ipp CHANGED
@@ -1,387 +1,387 @@
1
- #ifndef Rice__Data_Object__ipp_
2
- #define Rice__Data_Object__ipp_
3
-
4
- #include "Data_Type_defn.hpp"
5
-
6
- #include <algorithm>
7
-
8
- namespace Rice
9
- {
10
- template <typename T>
11
- Exception create_type_exception(VALUE value)
12
- {
13
- return Exception(rb_eTypeError, "Wrong argument type. Expected: %s. Received: %s.",
14
- detail::protect(rb_class2name, Data_Type<T>::klass().value()),
15
- detail::protect(rb_obj_classname, value));
16
- }
17
-
18
- template<typename T>
19
- inline Data_Object<T>::Data_Object(T& data, bool isOwner, Class klass)
20
- {
21
- VALUE value = detail::wrap(klass, Data_Type<T>::ruby_data_type(), data, isOwner);
22
- this->set_value(value);
23
- }
24
-
25
- template<typename T>
26
- inline Data_Object<T>::Data_Object(T* data, bool isOwner, Class klass)
27
- {
28
- VALUE value = detail::wrap(klass, Data_Type<T>::ruby_data_type(), data, isOwner);
29
- this->set_value(value);
30
- }
31
-
32
- template<typename T>
33
- inline Data_Object<T>::Data_Object(Object value) : Object(value)
34
- {
35
- check_ruby_type(value);
36
- }
37
-
38
- template<typename T>
39
- inline void Data_Object<T>::check_ruby_type(VALUE value)
40
- {
41
- if (rb_obj_is_kind_of(value, Data_Type<T>::klass()) == Qfalse)
42
- {
43
- throw create_type_exception<T>(value);
44
- }
45
- }
46
-
47
- template<typename T>
48
- inline T& Data_Object<T>::operator*() const
49
- {
50
- return *this->get();
51
- }
52
-
53
- template<typename T>
54
- inline T* Data_Object<T>::operator->() const
55
- {
56
- return this->get();
57
- }
58
-
59
- template<typename T>
60
- inline T* Data_Object<T>::get() const
61
- {
62
- if (this->value() == Qnil)
63
- {
64
- return nullptr;
65
- }
66
- else
67
- {
68
- return detail::unwrap<T>(this->value(), Data_Type<T>::ruby_data_type());
69
- }
70
- }
71
-
72
- template<typename T>
73
- inline T* Data_Object<T>::from_ruby(VALUE value)
74
- {
75
- if (Data_Type<T>::is_descendant(value))
76
- {
77
- return detail::unwrap<T>(value, Data_Type<T>::ruby_data_type());
78
- }
79
- else
80
- {
81
- throw create_type_exception<T>(value);
82
- }
83
- }
84
- }
85
-
86
- namespace Rice::detail
87
- {
88
- template<typename T>
89
- class To_Ruby
90
- {
91
- public:
92
- VALUE convert(T& data)
93
- {
94
- // Get the ruby typeinfo
95
- std::pair<VALUE, rb_data_type_t*> rubyTypeInfo = detail::Registries::instance.types.figureType<T>(data);
96
-
97
- // We always take ownership of data passed by value (yes the parameter is T& but the template
98
- // matched <typename T> thus we have to tell wrap to copy the reference we are sending to it
99
- return detail::wrap(rubyTypeInfo.first, rubyTypeInfo.second, data, true);
100
- }
101
-
102
- VALUE convert(const T& data)
103
- {
104
- // Get the ruby typeinfo
105
- std::pair<VALUE, rb_data_type_t*> rubyTypeInfo = detail::Registries::instance.types.figureType<T>(data);
106
-
107
- // We always take ownership of data passed by value (yes the parameter is T& but the template
108
- // matched <typename T> thus we have to tell wrap to copy the reference we are sending to it
109
- return detail::wrap(rubyTypeInfo.first, rubyTypeInfo.second, data, true);
110
- }
111
- };
112
-
113
- template <typename T>
114
- class To_Ruby<T&>
115
- {
116
- public:
117
- To_Ruby() = default;
118
-
119
- explicit To_Ruby(Return * returnInfo) : returnInfo_(returnInfo)
120
- {
121
- }
122
-
123
- VALUE convert(T& data)
124
- {
125
- // Note that T could be a pointer or reference to a base class while data is in fact a
126
- // child class. Lookup the correct type so we return an instance of the correct Ruby class
127
- std::pair<VALUE, rb_data_type_t*> rubyTypeInfo = detail::Registries::instance.types.figureType<T>(data);
128
-
129
- bool isOwner = this->returnInfo_ && this->returnInfo_->isOwner();
130
- return detail::wrap(rubyTypeInfo.first, rubyTypeInfo.second, data, isOwner);
131
- }
132
-
133
- VALUE convert(const T& data)
134
- {
135
- // Note that T could be a pointer or reference to a base class while data is in fact a
136
- // child class. Lookup the correct type so we return an instance of the correct Ruby class
137
- std::pair<VALUE, rb_data_type_t*> rubyTypeInfo = detail::Registries::instance.types.figureType<T>(data);
138
-
139
- bool isOwner = this->returnInfo_ && this->returnInfo_->isOwner();
140
- return detail::wrap(rubyTypeInfo.first, rubyTypeInfo.second, data, isOwner);
141
- }
142
-
143
- private:
144
- Return* returnInfo_ = nullptr;
145
- };
146
-
147
- template <typename T>
148
- class To_Ruby<T*>
149
- {
150
- public:
151
- To_Ruby() = default;
152
-
153
- explicit To_Ruby(Return* returnInfo) : returnInfo_(returnInfo)
154
- {
155
- }
156
-
157
- VALUE convert(T* data)
158
- {
159
- if (data)
160
- {
161
- // Note that T could be a pointer or reference to a base class while data is in fact a
162
- // child class. Lookup the correct type so we return an instance of the correct Ruby class
163
- std::pair<VALUE, rb_data_type_t*> rubyTypeInfo = detail::Registries::instance.types.figureType(*data);
164
- bool isOwner = this->returnInfo_ && this->returnInfo_->isOwner();
165
- return detail::wrap(rubyTypeInfo.first, rubyTypeInfo.second, data, isOwner);
166
- }
167
- else
168
- {
169
- return Qnil;
170
- }
171
- }
172
-
173
- VALUE convert(const T* data)
174
- {
175
- if (data)
176
- {
177
- // Note that T could be a pointer or reference to a base class while data is in fact a
178
- // child class. Lookup the correct type so we return an instance of the correct Ruby class
179
- std::pair<VALUE, rb_data_type_t*> rubyTypeInfo = detail::Registries::instance.types.figureType(*data);
180
- bool isOwner = this->returnInfo_ && this->returnInfo_->isOwner();
181
- return detail::wrap(rubyTypeInfo.first, rubyTypeInfo.second, data, isOwner);
182
- }
183
- else
184
- {
185
- return Qnil;
186
- }
187
- }
188
-
189
- private:
190
- Return* returnInfo_ = nullptr;
191
- };
192
-
193
- template <typename T>
194
- class To_Ruby<T*&>
195
- {
196
- public:
197
- To_Ruby() = default;
198
-
199
- explicit To_Ruby(Return* returnInfo) : returnInfo_(returnInfo)
200
- {
201
- }
202
-
203
- VALUE convert(T* data)
204
- {
205
- if (data)
206
- {
207
- // Note that T could be a pointer or reference to a base class while data is in fact a
208
- // child class. Lookup the correct type so we return an instance of the correct Ruby class
209
- std::pair<VALUE, rb_data_type_t*> rubyTypeInfo = detail::Registries::instance.types.figureType(*data);
210
- bool isOwner = this->returnInfo_ && this->returnInfo_->isOwner();
211
- return detail::wrap(rubyTypeInfo.first, rubyTypeInfo.second, data, isOwner);
212
- }
213
- else
214
- {
215
- return Qnil;
216
- }
217
- }
218
-
219
- VALUE convert(const T* data)
220
- {
221
- if (data)
222
- {
223
- // Note that T could be a pointer or reference to a base class while data is in fact a
224
- // child class. Lookup the correct type so we return an instance of the correct Ruby class
225
- std::pair<VALUE, rb_data_type_t*> rubyTypeInfo = detail::Registries::instance.types.figureType(*data);
226
- bool isOwner = this->returnInfo_ && this->returnInfo_->isOwner();
227
- return detail::wrap(rubyTypeInfo.first, rubyTypeInfo.second, data, isOwner);
228
- }
229
- else
230
- {
231
- return Qnil;
232
- }
233
- }
234
-
235
- private:
236
- Return* returnInfo_ = nullptr;
237
- };
238
-
239
- template<typename T>
240
- class To_Ruby<Data_Object<T>>
241
- {
242
- public:
243
- VALUE convert(const Object& x)
244
- {
245
- return x.value();
246
- }
247
- };
248
-
249
- template <typename T>
250
- class From_Ruby
251
- {
252
- static_assert(!std::is_fundamental_v<intrinsic_type<T>>,
253
- "Data_Object cannot be used with fundamental types");
254
- public:
255
- From_Ruby() = default;
256
-
257
- explicit From_Ruby(Arg * arg) : arg_(arg)
258
- {
259
- }
260
-
261
- bool is_convertible(VALUE value)
262
- {
263
- return rb_type(value) == RUBY_T_DATA &&
264
- Data_Type<T>::is_descendant(value);
265
- }
266
-
267
- T convert(VALUE value)
268
- {
269
- using Intrinsic_T = intrinsic_type<T>;
270
-
271
- if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
272
- {
273
- return this->arg_->template defaultValue<Intrinsic_T>();
274
- }
275
- else
276
- {
277
- return *Data_Object<Intrinsic_T>::from_ruby(value);
278
- }
279
- }
280
-
281
- private:
282
- Arg* arg_ = nullptr;
283
- };
284
-
285
- template<typename T>
286
- class From_Ruby<T&>
287
- {
288
- static_assert(!std::is_fundamental_v<intrinsic_type<T>>,
289
- "Data_Object cannot be used with fundamental types");
290
- public:
291
- From_Ruby() = default;
292
-
293
- explicit From_Ruby(Arg * arg) : arg_(arg)
294
- {
295
- }
296
-
297
- bool is_convertible(VALUE value)
298
- {
299
- return rb_type(value) == RUBY_T_DATA &&
300
- Data_Type<T>::is_descendant(value);
301
- }
302
-
303
- T& convert(VALUE value)
304
- {
305
- using Intrinsic_T = intrinsic_type<T>;
306
-
307
- if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
308
- {
309
- return this->arg_->template defaultValue<Intrinsic_T>();
310
- }
311
- else
312
- {
313
- return *Data_Object<Intrinsic_T>::from_ruby(value);
314
- }
315
- }
316
-
317
- private:
318
- Arg* arg_ = nullptr;
319
- };
320
-
321
- template<typename T>
322
- class From_Ruby<T*>
323
- {
324
- static_assert(!std::is_fundamental_v<intrinsic_type<T>>,
325
- "Data_Object cannot be used with fundamental types");
326
- public:
327
- bool is_convertible(VALUE value)
328
- {
329
- return rb_type(value) == RUBY_T_DATA &&
330
- Data_Type<T>::is_descendant(value);
331
- }
332
-
333
- T* convert(VALUE value)
334
- {
335
- using Intrinsic_T = intrinsic_type<T>;
336
-
337
- if (value == Qnil)
338
- {
339
- return nullptr;
340
- }
341
- else
342
- {
343
- return Data_Object<Intrinsic_T>::from_ruby(value);
344
- }
345
- }
346
- };
347
-
348
- template<typename T>
349
- class From_Ruby<T*&>
350
- {
351
- static_assert(!std::is_fundamental_v<intrinsic_type<T>>,
352
- "Data_Object cannot be used with fundamental types");
353
- public:
354
- bool is_convertible(VALUE value)
355
- {
356
- return rb_type(value) == RUBY_T_DATA &&
357
- Data_Type<T>::is_descendant(value);
358
- }
359
-
360
- T* convert(VALUE value)
361
- {
362
- using Intrinsic_T = intrinsic_type<T>;
363
-
364
- if (value == Qnil)
365
- {
366
- return nullptr;
367
- }
368
- else
369
- {
370
- return Data_Object<Intrinsic_T>::from_ruby(value);
371
- }
372
- }
373
- };
374
-
375
- template<typename T>
376
- class From_Ruby<Data_Object<T>>
377
- {
378
- static_assert(!std::is_fundamental_v<intrinsic_type<T>>,
379
- "Data_Object cannot be used with fundamental types");
380
- public:
381
- static Data_Object<T> convert(VALUE value)
382
- {
383
- return Data_Object<T>(value);
384
- }
385
- };
386
- }
1
+ #ifndef Rice__Data_Object__ipp_
2
+ #define Rice__Data_Object__ipp_
3
+
4
+ #include "Data_Type_defn.hpp"
5
+
6
+ #include <algorithm>
7
+
8
+ namespace Rice
9
+ {
10
+ template <typename T>
11
+ Exception create_type_exception(VALUE value)
12
+ {
13
+ return Exception(rb_eTypeError, "Wrong argument type. Expected: %s. Received: %s.",
14
+ detail::protect(rb_class2name, Data_Type<T>::klass().value()),
15
+ detail::protect(rb_obj_classname, value));
16
+ }
17
+
18
+ template<typename T>
19
+ inline Data_Object<T>::Data_Object(T& data, bool isOwner, Class klass)
20
+ {
21
+ VALUE value = detail::wrap(klass, Data_Type<T>::ruby_data_type(), data, isOwner);
22
+ this->set_value(value);
23
+ }
24
+
25
+ template<typename T>
26
+ inline Data_Object<T>::Data_Object(T* data, bool isOwner, Class klass)
27
+ {
28
+ VALUE value = detail::wrap(klass, Data_Type<T>::ruby_data_type(), data, isOwner);
29
+ this->set_value(value);
30
+ }
31
+
32
+ template<typename T>
33
+ inline Data_Object<T>::Data_Object(Object value) : Object(value)
34
+ {
35
+ check_ruby_type(value);
36
+ }
37
+
38
+ template<typename T>
39
+ inline void Data_Object<T>::check_ruby_type(VALUE value)
40
+ {
41
+ if (rb_obj_is_kind_of(value, Data_Type<T>::klass()) == Qfalse)
42
+ {
43
+ throw create_type_exception<T>(value);
44
+ }
45
+ }
46
+
47
+ template<typename T>
48
+ inline T& Data_Object<T>::operator*() const
49
+ {
50
+ return *this->get();
51
+ }
52
+
53
+ template<typename T>
54
+ inline T* Data_Object<T>::operator->() const
55
+ {
56
+ return this->get();
57
+ }
58
+
59
+ template<typename T>
60
+ inline T* Data_Object<T>::get() const
61
+ {
62
+ if (this->value() == Qnil)
63
+ {
64
+ return nullptr;
65
+ }
66
+ else
67
+ {
68
+ return detail::unwrap<T>(this->value(), Data_Type<T>::ruby_data_type());
69
+ }
70
+ }
71
+
72
+ template<typename T>
73
+ inline T* Data_Object<T>::from_ruby(VALUE value)
74
+ {
75
+ if (Data_Type<T>::is_descendant(value))
76
+ {
77
+ return detail::unwrap<T>(value, Data_Type<T>::ruby_data_type());
78
+ }
79
+ else
80
+ {
81
+ throw create_type_exception<T>(value);
82
+ }
83
+ }
84
+ }
85
+
86
+ namespace Rice::detail
87
+ {
88
+ template<typename T>
89
+ class To_Ruby
90
+ {
91
+ public:
92
+ VALUE convert(T& data)
93
+ {
94
+ // Get the ruby typeinfo
95
+ std::pair<VALUE, rb_data_type_t*> rubyTypeInfo = detail::Registries::instance.types.figureType<T>(data);
96
+
97
+ // We always take ownership of data passed by value (yes the parameter is T& but the template
98
+ // matched <typename T> thus we have to tell wrap to copy the reference we are sending to it
99
+ return detail::wrap(rubyTypeInfo.first, rubyTypeInfo.second, data, true);
100
+ }
101
+
102
+ VALUE convert(const T& data)
103
+ {
104
+ // Get the ruby typeinfo
105
+ std::pair<VALUE, rb_data_type_t*> rubyTypeInfo = detail::Registries::instance.types.figureType<T>(data);
106
+
107
+ // We always take ownership of data passed by value (yes the parameter is T& but the template
108
+ // matched <typename T> thus we have to tell wrap to copy the reference we are sending to it
109
+ return detail::wrap(rubyTypeInfo.first, rubyTypeInfo.second, data, true);
110
+ }
111
+ };
112
+
113
+ template <typename T>
114
+ class To_Ruby<T&>
115
+ {
116
+ public:
117
+ To_Ruby() = default;
118
+
119
+ explicit To_Ruby(Return * returnInfo) : returnInfo_(returnInfo)
120
+ {
121
+ }
122
+
123
+ VALUE convert(T& data)
124
+ {
125
+ // Note that T could be a pointer or reference to a base class while data is in fact a
126
+ // child class. Lookup the correct type so we return an instance of the correct Ruby class
127
+ std::pair<VALUE, rb_data_type_t*> rubyTypeInfo = detail::Registries::instance.types.figureType<T>(data);
128
+
129
+ bool isOwner = this->returnInfo_ && this->returnInfo_->isOwner();
130
+ return detail::wrap(rubyTypeInfo.first, rubyTypeInfo.second, data, isOwner);
131
+ }
132
+
133
+ VALUE convert(const T& data)
134
+ {
135
+ // Note that T could be a pointer or reference to a base class while data is in fact a
136
+ // child class. Lookup the correct type so we return an instance of the correct Ruby class
137
+ std::pair<VALUE, rb_data_type_t*> rubyTypeInfo = detail::Registries::instance.types.figureType<T>(data);
138
+
139
+ bool isOwner = this->returnInfo_ && this->returnInfo_->isOwner();
140
+ return detail::wrap(rubyTypeInfo.first, rubyTypeInfo.second, data, isOwner);
141
+ }
142
+
143
+ private:
144
+ Return* returnInfo_ = nullptr;
145
+ };
146
+
147
+ template <typename T>
148
+ class To_Ruby<T*>
149
+ {
150
+ public:
151
+ To_Ruby() = default;
152
+
153
+ explicit To_Ruby(Return* returnInfo) : returnInfo_(returnInfo)
154
+ {
155
+ }
156
+
157
+ VALUE convert(T* data)
158
+ {
159
+ if (data)
160
+ {
161
+ // Note that T could be a pointer or reference to a base class while data is in fact a
162
+ // child class. Lookup the correct type so we return an instance of the correct Ruby class
163
+ std::pair<VALUE, rb_data_type_t*> rubyTypeInfo = detail::Registries::instance.types.figureType(*data);
164
+ bool isOwner = this->returnInfo_ && this->returnInfo_->isOwner();
165
+ return detail::wrap(rubyTypeInfo.first, rubyTypeInfo.second, data, isOwner);
166
+ }
167
+ else
168
+ {
169
+ return Qnil;
170
+ }
171
+ }
172
+
173
+ VALUE convert(const T* data)
174
+ {
175
+ if (data)
176
+ {
177
+ // Note that T could be a pointer or reference to a base class while data is in fact a
178
+ // child class. Lookup the correct type so we return an instance of the correct Ruby class
179
+ std::pair<VALUE, rb_data_type_t*> rubyTypeInfo = detail::Registries::instance.types.figureType(*data);
180
+ bool isOwner = this->returnInfo_ && this->returnInfo_->isOwner();
181
+ return detail::wrap(rubyTypeInfo.first, rubyTypeInfo.second, data, isOwner);
182
+ }
183
+ else
184
+ {
185
+ return Qnil;
186
+ }
187
+ }
188
+
189
+ private:
190
+ Return* returnInfo_ = nullptr;
191
+ };
192
+
193
+ template <typename T>
194
+ class To_Ruby<T*&>
195
+ {
196
+ public:
197
+ To_Ruby() = default;
198
+
199
+ explicit To_Ruby(Return* returnInfo) : returnInfo_(returnInfo)
200
+ {
201
+ }
202
+
203
+ VALUE convert(T* data)
204
+ {
205
+ if (data)
206
+ {
207
+ // Note that T could be a pointer or reference to a base class while data is in fact a
208
+ // child class. Lookup the correct type so we return an instance of the correct Ruby class
209
+ std::pair<VALUE, rb_data_type_t*> rubyTypeInfo = detail::Registries::instance.types.figureType(*data);
210
+ bool isOwner = this->returnInfo_ && this->returnInfo_->isOwner();
211
+ return detail::wrap(rubyTypeInfo.first, rubyTypeInfo.second, data, isOwner);
212
+ }
213
+ else
214
+ {
215
+ return Qnil;
216
+ }
217
+ }
218
+
219
+ VALUE convert(const T* data)
220
+ {
221
+ if (data)
222
+ {
223
+ // Note that T could be a pointer or reference to a base class while data is in fact a
224
+ // child class. Lookup the correct type so we return an instance of the correct Ruby class
225
+ std::pair<VALUE, rb_data_type_t*> rubyTypeInfo = detail::Registries::instance.types.figureType(*data);
226
+ bool isOwner = this->returnInfo_ && this->returnInfo_->isOwner();
227
+ return detail::wrap(rubyTypeInfo.first, rubyTypeInfo.second, data, isOwner);
228
+ }
229
+ else
230
+ {
231
+ return Qnil;
232
+ }
233
+ }
234
+
235
+ private:
236
+ Return* returnInfo_ = nullptr;
237
+ };
238
+
239
+ template<typename T>
240
+ class To_Ruby<Data_Object<T>>
241
+ {
242
+ public:
243
+ VALUE convert(const Object& x)
244
+ {
245
+ return x.value();
246
+ }
247
+ };
248
+
249
+ template <typename T>
250
+ class From_Ruby
251
+ {
252
+ static_assert(!std::is_fundamental_v<intrinsic_type<T>>,
253
+ "Data_Object cannot be used with fundamental types");
254
+ public:
255
+ From_Ruby() = default;
256
+
257
+ explicit From_Ruby(Arg * arg) : arg_(arg)
258
+ {
259
+ }
260
+
261
+ bool is_convertible(VALUE value)
262
+ {
263
+ return rb_type(value) == RUBY_T_DATA &&
264
+ Data_Type<T>::is_descendant(value);
265
+ }
266
+
267
+ T convert(VALUE value)
268
+ {
269
+ using Intrinsic_T = intrinsic_type<T>;
270
+
271
+ if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
272
+ {
273
+ return this->arg_->template defaultValue<Intrinsic_T>();
274
+ }
275
+ else
276
+ {
277
+ return *Data_Object<Intrinsic_T>::from_ruby(value);
278
+ }
279
+ }
280
+
281
+ private:
282
+ Arg* arg_ = nullptr;
283
+ };
284
+
285
+ template<typename T>
286
+ class From_Ruby<T&>
287
+ {
288
+ static_assert(!std::is_fundamental_v<intrinsic_type<T>>,
289
+ "Data_Object cannot be used with fundamental types");
290
+ public:
291
+ From_Ruby() = default;
292
+
293
+ explicit From_Ruby(Arg * arg) : arg_(arg)
294
+ {
295
+ }
296
+
297
+ bool is_convertible(VALUE value)
298
+ {
299
+ return rb_type(value) == RUBY_T_DATA &&
300
+ Data_Type<T>::is_descendant(value);
301
+ }
302
+
303
+ T& convert(VALUE value)
304
+ {
305
+ using Intrinsic_T = intrinsic_type<T>;
306
+
307
+ if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue())
308
+ {
309
+ return this->arg_->template defaultValue<Intrinsic_T>();
310
+ }
311
+ else
312
+ {
313
+ return *Data_Object<Intrinsic_T>::from_ruby(value);
314
+ }
315
+ }
316
+
317
+ private:
318
+ Arg* arg_ = nullptr;
319
+ };
320
+
321
+ template<typename T>
322
+ class From_Ruby<T*>
323
+ {
324
+ static_assert(!std::is_fundamental_v<intrinsic_type<T>>,
325
+ "Data_Object cannot be used with fundamental types");
326
+ public:
327
+ bool is_convertible(VALUE value)
328
+ {
329
+ return rb_type(value) == RUBY_T_DATA &&
330
+ Data_Type<T>::is_descendant(value);
331
+ }
332
+
333
+ T* convert(VALUE value)
334
+ {
335
+ using Intrinsic_T = intrinsic_type<T>;
336
+
337
+ if (value == Qnil)
338
+ {
339
+ return nullptr;
340
+ }
341
+ else
342
+ {
343
+ return Data_Object<Intrinsic_T>::from_ruby(value);
344
+ }
345
+ }
346
+ };
347
+
348
+ template<typename T>
349
+ class From_Ruby<T*&>
350
+ {
351
+ static_assert(!std::is_fundamental_v<intrinsic_type<T>>,
352
+ "Data_Object cannot be used with fundamental types");
353
+ public:
354
+ bool is_convertible(VALUE value)
355
+ {
356
+ return rb_type(value) == RUBY_T_DATA &&
357
+ Data_Type<T>::is_descendant(value);
358
+ }
359
+
360
+ T* convert(VALUE value)
361
+ {
362
+ using Intrinsic_T = intrinsic_type<T>;
363
+
364
+ if (value == Qnil)
365
+ {
366
+ return nullptr;
367
+ }
368
+ else
369
+ {
370
+ return Data_Object<Intrinsic_T>::from_ruby(value);
371
+ }
372
+ }
373
+ };
374
+
375
+ template<typename T>
376
+ class From_Ruby<Data_Object<T>>
377
+ {
378
+ static_assert(!std::is_fundamental_v<intrinsic_type<T>>,
379
+ "Data_Object cannot be used with fundamental types");
380
+ public:
381
+ static Data_Object<T> convert(VALUE value)
382
+ {
383
+ return Data_Object<T>(value);
384
+ }
385
+ };
386
+ }
387
387
  #endif // Rice__Data_Object__ipp_