@@ -381,11 +381,33 @@ class type_caster_generic {
381
381
object temp;
382
382
};
383
383
384
- /* Determine suitable casting operator */
384
+ /* *
385
+ * Determine suitable casting operator for pointer-or-lvalue-casting type casters. The type caster
386
+ * needs to provide `operator T*()` and `operator T&()` operators.
387
+ *
388
+ * If the type supports moving the value away via an `operator T&&() &&` method, it should use
389
+ * `movable_cast_op_type` instead.
390
+ */
385
391
template <typename T>
386
- using cast_op_type = typename std::conditional<std::is_pointer<typename std::remove_reference<T>::type>::value,
387
- typename std::add_pointer<intrinsic_t <T>>::type,
388
- typename std::add_lvalue_reference<intrinsic_t <T>>::type>::type;
392
+ using cast_op_type =
393
+ conditional_t <std::is_pointer<typename std::remove_reference<T>::type>::value,
394
+ typename std::add_pointer<intrinsic_t <T>>::type,
395
+ typename std::add_lvalue_reference<intrinsic_t <T>>::type>;
396
+
397
+ /* *
398
+ * Determine suitable casting operator for a type caster with a movable value. Such a type caster
399
+ * needs to provide `operator T*()`, `operator T&()`, and `operator T&&() &&`. The latter will be
400
+ * called in appropriate contexts where the value can be moved rather than copied.
401
+ *
402
+ * These operator are automatically provided when using the PYBIND11_TYPE_CASTER macro.
403
+ */
404
+ template <typename T>
405
+ using movable_cast_op_type =
406
+ conditional_t <std::is_pointer<typename std::remove_reference<T>::type>::value,
407
+ typename std::add_pointer<intrinsic_t <T>>::type,
408
+ conditional_t <std::is_rvalue_reference<T>::value,
409
+ typename std::add_rvalue_reference<intrinsic_t <T>>::type,
410
+ typename std::add_lvalue_reference<intrinsic_t <T>>::type>>;
389
411
390
412
// std::is_copy_constructible isn't quite enough: it lets std::vector<T> (and similar) through when
391
413
// T is non-copyable, but code containing such a copy constructor fails to actually compile.
@@ -462,7 +484,7 @@ template <typename type> class type_caster_base : public type_caster_generic {
462
484
nullptr , nullptr , holder);
463
485
}
464
486
465
- template <typename T> using cast_op_type = pybind11::detail:: cast_op_type<T>;
487
+ template <typename T> using cast_op_type = cast_op_type<T>;
466
488
467
489
operator itype*() { return (type *) value; }
468
490
operator itype&() { if (!value) throw reference_cast_error (); return *((itype *) value); }
@@ -498,8 +520,10 @@ template <typename type> using make_caster = type_caster<intrinsic_t<type>>;
498
520
template <typename T> typename make_caster<T>::template cast_op_type<T> cast_op (make_caster<T> &caster) {
499
521
return caster.operator typename make_caster<T>::template cast_op_type<T>();
500
522
}
501
- template <typename T> typename make_caster<T>::template cast_op_type<T> cast_op (make_caster<T> &&caster) {
502
- return cast_op<T>(caster);
523
+ template <typename T> typename make_caster<T>::template cast_op_type<typename std::add_rvalue_reference<T>::type>
524
+ cast_op (make_caster<T> &&caster) {
525
+ return std::move (caster).operator
526
+ typename make_caster<T>::template cast_op_type<typename std::add_rvalue_reference<T>::type>();
503
527
}
504
528
505
529
template <typename type> class type_caster <std::reference_wrapper<type>> : public type_caster_base<type> {
@@ -522,7 +546,8 @@ template <typename type> class type_caster<std::reference_wrapper<type>> : publi
522
546
} \
523
547
operator type*() { return &value; } \
524
548
operator type&() { return value; } \
525
- template <typename _T> using cast_op_type = pybind11::detail::cast_op_type<_T>
549
+ operator type&&() && { return std::move (value); } \
550
+ template <typename _T> using cast_op_type = pybind11::detail::movable_cast_op_type<_T>
526
551
527
552
528
553
template <typename CharT> using is_std_char_type = any_of<
@@ -892,9 +917,8 @@ template <typename T1, typename T2> class type_caster<std::pair<T1, T2>> {
892
917
893
918
template <typename T> using cast_op_type = type;
894
919
895
- operator type () {
896
- return type (cast_op<T1>(first), cast_op<T2>(second));
897
- }
920
+ operator type () & { return type (cast_op<T1>(first), cast_op<T2>(second)); }
921
+ operator type () && { return type (cast_op<T1>(std::move (first)), cast_op<T2>(std::move (second))); }
898
922
protected:
899
923
make_caster<T1> first;
900
924
make_caster<T2> second;
@@ -925,17 +949,21 @@ template <typename... Tuple> class type_caster<std::tuple<Tuple...>> {
925
949
926
950
template <typename T> using cast_op_type = type;
927
951
928
- operator type () { return implicit_cast (indices{}); }
952
+ operator type () & { return implicit_cast (indices{}); }
953
+ operator type () && { return std::move (*this ).implicit_cast (indices{}); }
929
954
930
955
protected:
931
956
template <size_t ... Is>
932
- type implicit_cast (index_sequence<Is...>) { return type (cast_op<Tuple>(std::get<Is>(value))...); }
957
+ type implicit_cast (index_sequence<Is...>) & { return type (cast_op<Tuple>(std::get<Is>(subcasters))...); }
958
+ template <size_t ... Is>
959
+ type implicit_cast (index_sequence<Is...>) && { return type (cast_op<Tuple>(std::move (std::get<Is>(subcasters)))...); }
960
+
933
961
934
962
static constexpr bool load_impl (const sequence &, bool , index_sequence<>) { return true ; }
935
963
936
964
template <size_t ... Is>
937
965
bool load_impl (const sequence &seq, bool convert, index_sequence<Is...>) {
938
- for (bool r : {std::get<Is>(value ).load (seq[Is], convert)...})
966
+ for (bool r : {std::get<Is>(subcasters ).load (seq[Is], convert)...})
939
967
if (!r)
940
968
return false ;
941
969
return true ;
@@ -960,7 +988,7 @@ template <typename... Tuple> class type_caster<std::tuple<Tuple...>> {
960
988
return result.release ();
961
989
}
962
990
963
- std::tuple<make_caster<Tuple>...> value ;
991
+ std::tuple<make_caster<Tuple>...> subcasters ;
964
992
};
965
993
966
994
// / Helper class which abstracts away certain actions. Users can provide specializations for
@@ -1465,13 +1493,13 @@ class argument_loader {
1465
1493
}
1466
1494
1467
1495
template <typename Return, typename Guard, typename Func>
1468
- enable_if_t <!std::is_void<Return>::value, Return> call (Func &&f) {
1469
- return call_impl<Return>(std::forward<Func>(f), indices{}, Guard{});
1496
+ enable_if_t <!std::is_void<Return>::value, Return> call (Func &&f) && {
1497
+ return std::move (* this ). template call_impl <Return>(std::forward<Func>(f), indices{}, Guard{});
1470
1498
}
1471
1499
1472
1500
template <typename Return, typename Guard, typename Func>
1473
- enable_if_t <std::is_void<Return>::value, void_type> call (Func &&f) {
1474
- call_impl<Return>(std::forward<Func>(f), indices{}, Guard{});
1501
+ enable_if_t <std::is_void<Return>::value, void_type> call (Func &&f) && {
1502
+ std::move (* this ). template call_impl <Return>(std::forward<Func>(f), indices{}, Guard{});
1475
1503
return void_type ();
1476
1504
}
1477
1505
@@ -1481,18 +1509,18 @@ class argument_loader {
1481
1509
1482
1510
template <size_t ... Is>
1483
1511
bool load_impl_sequence (function_call &call, index_sequence<Is...>) {
1484
- for (bool r : {std::get<Is>(value ).load (call.args [Is], call.args_convert [Is])...})
1512
+ for (bool r : {std::get<Is>(argcasters ).load (call.args [Is], call.args_convert [Is])...})
1485
1513
if (!r)
1486
1514
return false ;
1487
1515
return true ;
1488
1516
}
1489
1517
1490
1518
template <typename Return, typename Func, size_t ... Is, typename Guard>
1491
1519
Return call_impl (Func &&f, index_sequence<Is...>, Guard &&) {
1492
- return std::forward<Func>(f)(cast_op<Args>(std::get<Is>(value ))...);
1520
+ return std::forward<Func>(f)(cast_op<Args>(std::move (std:: get<Is>(argcasters) ))...);
1493
1521
}
1494
1522
1495
- std::tuple<make_caster<Args>...> value ;
1523
+ std::tuple<make_caster<Args>...> argcasters ;
1496
1524
};
1497
1525
1498
1526
// / Helper class which collects only positional arguments for a Python function call.
0 commit comments