@@ -40,6 +40,9 @@ enum cast_flags : uint8_t {
40
40
41
41
// Don't accept 'None' Python objects in the base class caster
42
42
none_disallowed = (1 << 2 ),
43
+
44
+ // Indicates that this cast is performed by nb::cast or nb::try_cast
45
+ manual = (1 << 3 )
43
46
};
44
47
45
48
/* *
@@ -411,53 +414,86 @@ template <typename Type_> struct type_caster_base : type_caster_base_tag {
411
414
template <typename Type, typename SFINAE>
412
415
struct type_caster : type_caster_base<Type> { };
413
416
414
- NAMESPACE_END (detail)
417
+ template <bool Convert, typename T>
418
+ T cast_impl (handle h) {
419
+ using Caster = detail::make_caster<T>;
415
420
416
- template <typename T, typename Derived>
417
- bool try_cast(const detail::api<Derived> &value, T &out, bool convert = true ) noexcept {
421
+ static_assert (
422
+ !(std::is_reference_v<T> || std::is_pointer_v<T>) ||
423
+ detail::is_base_caster_v<Caster> ||
424
+ std::is_same_v<const char *, T>,
425
+ " nanobind::cast(): cannot return a reference to a temporary." );
426
+
427
+ Caster caster;
428
+ bool rv;
429
+ if constexpr (Convert) {
430
+ cleanup_list cleanup (nullptr );
431
+ rv = caster.from_python (h.ptr (),
432
+ ((uint8_t ) cast_flags::convert) |
433
+ ((uint8_t ) cast_flags::manual),
434
+ &cleanup);
435
+ cleanup.release (); // 'from_python' is 'noexcept', so this always runs
436
+ } else {
437
+ rv = caster.from_python (h.ptr (), (uint8_t ) cast_flags::manual, nullptr );
438
+ }
439
+
440
+ if (!rv)
441
+ detail::raise_cast_error ();
442
+ return caster.operator detail::cast_t <T>();
443
+ }
444
+
445
+ template <bool Convert, typename T>
446
+ bool try_cast_impl (handle h, T &out) noexcept {
418
447
using Caster = detail::make_caster<T>;
419
448
420
449
static_assert (!std::is_same_v<const char *, T>,
421
450
" nanobind::try_cast(): cannot return a reference to a temporary." );
422
451
423
452
Caster caster;
424
- if (caster.from_python (value.derived ().ptr (),
425
- convert ? (uint8_t ) detail::cast_flags::convert
426
- : (uint8_t ) 0 , nullptr )) {
453
+ bool rv;
454
+ if constexpr (Convert) {
455
+ cleanup_list cleanup (nullptr );
456
+ rv = caster.from_python (h.ptr (),
457
+ ((uint8_t ) cast_flags::convert) |
458
+ ((uint8_t ) cast_flags::manual),
459
+ &cleanup);
460
+ cleanup.release (); // 'from_python' is 'noexcept', so this always runs
461
+ } else {
462
+ rv = caster.from_python (h.ptr (), (uint8_t ) cast_flags::manual, nullptr );
463
+ }
464
+
465
+ if (rv) {
427
466
try {
428
467
out = caster.operator detail::cast_t <T>();
429
468
return true ;
430
- } catch (const builtin_exception&) {
431
- return false ;
432
- }
469
+ } catch (const builtin_exception&) { }
433
470
}
434
471
435
472
return false ;
436
473
}
437
474
475
+ NAMESPACE_END (detail)
476
+
438
477
template <typename T, typename Derived>
439
- T cast (const detail::api<Derived> &value, bool convert = true ) {
478
+ NB_INLINE T cast(const detail::api<Derived> &value, bool convert = true ) {
440
479
if constexpr (std::is_same_v<T, void >) {
441
480
return ;
442
481
} else {
443
- using Caster = detail::make_caster<T>;
444
-
445
- static_assert (
446
- !(std::is_reference_v<T> || std::is_pointer_v<T>) ||
447
- detail::is_base_caster_v<Caster> ||
448
- std::is_same_v<const char *, T>,
449
- " nanobind::cast(): cannot return a reference to a temporary." );
450
-
451
- Caster caster;
452
- if (!caster.from_python (value.derived ().ptr (),
453
- convert ? (uint8_t ) detail::cast_flags::convert
454
- : (uint8_t ) 0 , nullptr ))
455
- detail::raise_cast_error ();
456
-
457
- return caster.operator detail::cast_t <T>();
482
+ if (convert)
483
+ return detail::cast_impl<true , T>(value);
484
+ else
485
+ return detail::cast_impl<false , T>(value);
458
486
}
459
487
}
460
488
489
+ template <typename T, typename Derived>
490
+ NB_INLINE bool try_cast (const detail::api<Derived> &value, T &out, bool convert = true ) noexcept {
491
+ if (convert)
492
+ return detail::try_cast_impl<true , T>(value, out);
493
+ else
494
+ return detail::try_cast_impl<false , T>(value, out);
495
+ }
496
+
461
497
template <typename T>
462
498
object cast (T &&value, rv_policy policy = rv_policy::automatic_reference) {
463
499
handle h = detail::make_caster<T>::from_cpp ((detail::forward_t <T>) value,
0 commit comments