@@ -374,11 +374,31 @@ class type_caster_generic {
374
374
object temp;
375
375
};
376
376
377
- /* Determine suitable casting operator */
377
+ /* * Determine suitable casting operator for pointer-or-lvalue-casting type casters. The type caster
378
+ * needs to provide `operator T*()` and `operator T&()` operators.
379
+ *
380
+ * If the type supports moving the value away via an `operator T&&() &&` method, it should use
381
+ * `movable_cast_op_type` instead.
382
+ */
378
383
template <typename T>
379
- using cast_op_type = typename std::conditional<std::is_pointer<typename std::remove_reference<T>::type>::value,
380
- typename std::add_pointer<intrinsic_t <T>>::type,
381
- typename std::add_lvalue_reference<intrinsic_t <T>>::type>::type;
384
+ using cast_op_type =
385
+ conditional_t <std::is_pointer<typename std::remove_reference<T>::type>::value,
386
+ typename std::add_pointer<intrinsic_t <T>>::type,
387
+ typename std::add_lvalue_reference<intrinsic_t <T>>::type>;
388
+
389
+ /* * Determine suitable casting operator for a type caster with a movable value. Such a type caster
390
+ * needs to provide `operator T*()`, `operator T&()`, and `operator T&&() &&`. The latter will be
391
+ * called in appropriate contexts where the value can be moved rather than copied.
392
+ *
393
+ * These operator are automatically provided when using the PYBIND11_TYPE_CASTER macro.
394
+ */
395
+ template <typename T>
396
+ using movable_cast_op_type =
397
+ conditional_t <std::is_pointer<typename std::remove_reference<T>::type>::value,
398
+ typename std::add_pointer<intrinsic_t <T>>::type,
399
+ conditional_t <std::is_rvalue_reference<T>::value,
400
+ typename std::add_rvalue_reference<intrinsic_t <T>>::type,
401
+ typename std::add_lvalue_reference<intrinsic_t <T>>::type>>;
382
402
383
403
// std::is_copy_constructible isn't quite enough: it lets std::vector<T> (and similar) through when
384
404
// T is non-copyable, but code containing such a copy constructor fails to actually compile.
@@ -455,7 +475,7 @@ template <typename type> class type_caster_base : public type_caster_generic {
455
475
nullptr , nullptr , holder);
456
476
}
457
477
458
- template <typename T> using cast_op_type = pybind11::detail:: cast_op_type<T>;
478
+ template <typename T> using cast_op_type = cast_op_type<T>;
459
479
460
480
operator itype*() { return (type *) value; }
461
481
operator itype&() { if (!value) throw reference_cast_error (); return *((itype *) value); }
@@ -491,8 +511,10 @@ template <typename type> using make_caster = type_caster<intrinsic_t<type>>;
491
511
template <typename T> typename make_caster<T>::template cast_op_type<T> cast_op (make_caster<T> &caster) {
492
512
return caster.operator typename make_caster<T>::template cast_op_type<T>();
493
513
}
494
- template <typename T> typename make_caster<T>::template cast_op_type<T> cast_op (make_caster<T> &&caster) {
495
- return cast_op<T>(caster);
514
+ template <typename T> typename make_caster<T>::template cast_op_type<typename std::add_rvalue_reference<T>::type>
515
+ cast_op (make_caster<T> &&caster) {
516
+ return std::move (caster).operator
517
+ typename make_caster<T>::template cast_op_type<typename std::add_rvalue_reference<T>::type>();
496
518
}
497
519
498
520
template <typename type> class type_caster <std::reference_wrapper<type>> : public type_caster_base<type> {
@@ -515,7 +537,8 @@ template <typename type> class type_caster<std::reference_wrapper<type>> : publi
515
537
} \
516
538
operator type*() { return &value; } \
517
539
operator type&() { return value; } \
518
- template <typename _T> using cast_op_type = pybind11::detail::cast_op_type<_T>
540
+ operator type&&() && { return std::move (value); } \
541
+ template <typename _T> using cast_op_type = pybind11::detail::movable_cast_op_type<_T>
519
542
520
543
521
544
template <typename CharT> using is_std_char_type = any_of<
@@ -885,9 +908,8 @@ template <typename T1, typename T2> class type_caster<std::pair<T1, T2>> {
885
908
886
909
template <typename T> using cast_op_type = type;
887
910
888
- operator type () {
889
- return type (cast_op<T1>(first), cast_op<T2>(second));
890
- }
911
+ operator type () & { return type (cast_op<T1>(first), cast_op<T2>(second)); }
912
+ operator type () && { return type (cast_op<T1>(std::move (first)), cast_op<T2>(std::move (second))); }
891
913
protected:
892
914
make_caster<T1> first;
893
915
make_caster<T2> second;
@@ -918,17 +940,21 @@ template <typename... Tuple> class type_caster<std::tuple<Tuple...>> {
918
940
919
941
template <typename T> using cast_op_type = type;
920
942
921
- operator type () { return implicit_cast (indices{}); }
943
+ operator type () & { return implicit_cast (indices{}); }
944
+ operator type () && { return std::move (*this ).implicit_cast (indices{}); }
922
945
923
946
protected:
924
947
template <size_t ... Is>
925
- type implicit_cast (index_sequence<Is...>) { return type (cast_op<Tuple>(std::get<Is>(value))...); }
948
+ type implicit_cast (index_sequence<Is...>) & { return type (cast_op<Tuple>(std::get<Is>(subcasters))...); }
949
+ template <size_t ... Is>
950
+ type implicit_cast (index_sequence<Is...>) && { return type (cast_op<Tuple>(std::move (std::get<Is>(subcasters)))...); }
951
+
926
952
927
953
static constexpr bool load_impl (const sequence &, bool , index_sequence<>) { return true ; }
928
954
929
955
template <size_t ... Is>
930
956
bool load_impl (const sequence &seq, bool convert, index_sequence<Is...>) {
931
- for (bool r : {std::get<Is>(value ).load (seq[Is], convert)...})
957
+ for (bool r : {std::get<Is>(subcasters ).load (seq[Is], convert)...})
932
958
if (!r)
933
959
return false ;
934
960
return true ;
@@ -953,7 +979,7 @@ template <typename... Tuple> class type_caster<std::tuple<Tuple...>> {
953
979
return result.release ();
954
980
}
955
981
956
- std::tuple<make_caster<Tuple>...> value ;
982
+ std::tuple<make_caster<Tuple>...> subcasters ;
957
983
};
958
984
959
985
// / Helper class which abstracts away certain actions. Users can provide specializations for
@@ -1458,13 +1484,13 @@ class argument_loader {
1458
1484
}
1459
1485
1460
1486
template <typename Return, typename Guard, typename Func>
1461
- enable_if_t <!std::is_void<Return>::value, Return> call (Func &&f) {
1462
- return call_impl<Return>(std::forward<Func>(f), indices{}, Guard{});
1487
+ enable_if_t <!std::is_void<Return>::value, Return> call (Func &&f) && {
1488
+ return std::move (* this ). template call_impl <Return>(std::forward<Func>(f), indices{}, Guard{});
1463
1489
}
1464
1490
1465
1491
template <typename Return, typename Guard, typename Func>
1466
- enable_if_t <std::is_void<Return>::value, void_type> call (Func &&f) {
1467
- call_impl<Return>(std::forward<Func>(f), indices{}, Guard{});
1492
+ enable_if_t <std::is_void<Return>::value, void_type> call (Func &&f) && {
1493
+ std::move (* this ). template call_impl <Return>(std::forward<Func>(f), indices{}, Guard{});
1468
1494
return void_type ();
1469
1495
}
1470
1496
@@ -1474,18 +1500,18 @@ class argument_loader {
1474
1500
1475
1501
template <size_t ... Is>
1476
1502
bool load_impl_sequence (function_call &call, index_sequence<Is...>) {
1477
- for (bool r : {std::get<Is>(value ).load (call.args [Is], call.args_convert [Is])...})
1503
+ for (bool r : {std::get<Is>(argcasters ).load (call.args [Is], call.args_convert [Is])...})
1478
1504
if (!r)
1479
1505
return false ;
1480
1506
return true ;
1481
1507
}
1482
1508
1483
1509
template <typename Return, typename Func, size_t ... Is, typename Guard>
1484
1510
Return call_impl (Func &&f, index_sequence<Is...>, Guard &&) {
1485
- return std::forward<Func>(f)(cast_op<Args>(std::get<Is>(value ))...);
1511
+ return std::forward<Func>(f)(cast_op<Args>(std::move (std:: get<Is>(argcasters) ))...);
1486
1512
}
1487
1513
1488
- std::tuple<make_caster<Args>...> value ;
1514
+ std::tuple<make_caster<Args>...> argcasters ;
1489
1515
};
1490
1516
1491
1517
// / Helper class which collects only positional arguments for a Python function call.
0 commit comments