Clean up cast operator invocations (#531)

This adds a `detail::cast_op<T>(caster)` function which handles the
rather verbose:

    caster.operator typename CasterType::template cast_op_type<T>()

which allows various places to use the shorter and clearer:

    cast_op<T>(caster)

instead of the full verbose cast operator invocation.
This commit is contained in:
Jason Rhinelander 2016-11-25 12:35:00 -05:00 committed by Wenzel Jakob
parent f200493716
commit db86f7f285
2 changed files with 22 additions and 17 deletions

View File

@ -432,6 +432,16 @@ protected:
template <typename type, typename SFINAE = void> class type_caster : public type_caster_base<type> { }; template <typename type, typename SFINAE = void> class type_caster : public type_caster_base<type> { };
template <typename type> using make_caster = type_caster<intrinsic_t<type>>; template <typename type> using make_caster = type_caster<intrinsic_t<type>>;
// Shortcut for calling a caster's `cast_op_type` cast operator for casting a type_caster to a T
template <typename T>
auto cast_op(make_caster<T> &caster) -> decltype(caster.operator typename make_caster<T>::template cast_op_type<T>()) {
return caster.operator typename make_caster<T>::template cast_op_type<T>();
}
template <typename T>
auto cast_op(make_caster<T> &&caster) -> decltype(caster.operator typename make_caster<T>::template cast_op_type<T>()) {
return cast_op<T>(caster);
}
template <typename type> class type_caster<std::reference_wrapper<type>> : public type_caster_base<type> { template <typename type> class type_caster<std::reference_wrapper<type>> : public type_caster_base<type> {
public: public:
static handle cast(const std::reference_wrapper<type> &src, return_value_policy policy, handle parent) { static handle cast(const std::reference_wrapper<type> &src, return_value_policy policy, handle parent) {
@ -757,8 +767,7 @@ public:
template <typename T> using cast_op_type = type; template <typename T> using cast_op_type = type;
operator type() { operator type() {
return type(first.operator typename make_caster<T1>::template cast_op_type<T1>(), return type(cast_op<T1>(first), cast_op<T2>(second));
second.operator typename make_caster<T2>::template cast_op_type<T2>());
} }
protected: protected:
make_caster<T1> first; make_caster<T1> first;
@ -831,13 +840,11 @@ public:
protected: protected:
template <typename ReturnValue, typename Func, size_t ... Index> ReturnValue call(Func &&f, index_sequence<Index...>) { template <typename ReturnValue, typename Func, size_t ... Index> ReturnValue call(Func &&f, index_sequence<Index...>) {
return f(std::get<Index>(value) return f(cast_op<Tuple>(std::get<Index>(value))...);
.operator typename make_caster<Tuple>::template cast_op_type<Tuple>()...);
} }
template <size_t ... Index> type cast(index_sequence<Index...>) { template <size_t ... Index> type cast(index_sequence<Index...>) {
return type(std::get<Index>(value) return type(cast_op<Tuple>(std::get<Index>(value))...);
.operator typename make_caster<Tuple>::template cast_op_type<Tuple>()...);
} }
template <size_t ... Indices> bool load(handle src, bool convert, index_sequence<Indices...>) { template <size_t ... Indices> bool load(handle src, bool convert, index_sequence<Indices...>) {
@ -1081,10 +1088,10 @@ NAMESPACE_END(detail)
// pytype -> C++ type // pytype -> C++ type
template <typename T, detail::enable_if_t<!detail::is_pyobject<T>::value, int> = 0> template <typename T, detail::enable_if_t<!detail::is_pyobject<T>::value, int> = 0>
T cast(const handle &handle) { T cast(const handle &handle) {
static_assert(!detail::cast_is_temporary_value_reference<T>::value, using namespace detail;
static_assert(!cast_is_temporary_value_reference<T>::value,
"Unable to cast type to reference: value is local to type caster"); "Unable to cast type to reference: value is local to type caster");
using type_caster = detail::make_caster<T>; return cast_op<T>(load_type<T>(handle));
return detail::load_type<T>(handle).operator typename type_caster::template cast_op_type<T>();
} }
// pytype -> pytype (calls converting constructor) // pytype -> pytype (calls converting constructor)
@ -1153,7 +1160,7 @@ template <typename ret_type> using overload_caster_t = conditional_t<
// Trampoline use: for reference/pointer types to value-converted values, we do a value cast, then // Trampoline use: for reference/pointer types to value-converted values, we do a value cast, then
// store the result in the given variable. For other types, this is a no-op. // store the result in the given variable. For other types, this is a no-op.
template <typename T> enable_if_t<cast_is_temporary_value_reference<T>::value, T> cast_ref(object &&o, make_caster<T> &caster) { template <typename T> enable_if_t<cast_is_temporary_value_reference<T>::value, T> cast_ref(object &&o, make_caster<T> &caster) {
return load_type(caster, o).operator typename make_caster<T>::template cast_op_type<T>(); return cast_op<T>(load_type(caster, o));
} }
template <typename T> enable_if_t<!cast_is_temporary_value_reference<T>::value, T> cast_ref(object &&, overload_unused &) { template <typename T> enable_if_t<!cast_is_temporary_value_reference<T>::value, T> cast_ref(object &&, overload_unused &) {
pybind11_fail("Internal error: cast_ref fallback invoked"); } pybind11_fail("Internal error: cast_ref fallback invoked"); }

View File

@ -53,7 +53,7 @@ template <typename Type, typename Key> struct set_caster {
for (auto entry : s) { for (auto entry : s) {
if (!conv.load(entry, convert)) if (!conv.load(entry, convert))
return false; return false;
value.insert(conv.operator typename key_conv::template cast_op_type<Key>()); value.insert(cast_op<Key>(conv));
} }
return true; return true;
} }
@ -87,9 +87,7 @@ template <typename Type, typename Key, typename Value> struct map_caster {
if (!kconv.load(it.first.ptr(), convert) || if (!kconv.load(it.first.ptr(), convert) ||
!vconv.load(it.second.ptr(), convert)) !vconv.load(it.second.ptr(), convert))
return false; return false;
value.emplace( value.emplace(cast_op<Key>(kconv), cast_op<Value>(vconv));
kconv.operator typename key_conv::template cast_op_type<Key>(),
vconv.operator typename value_conv::template cast_op_type<Value>());
} }
return true; return true;
} }
@ -123,7 +121,7 @@ template <typename Type, typename Value> struct list_caster {
for (auto it : s) { for (auto it : s) {
if (!conv.load(it, convert)) if (!conv.load(it, convert))
return false; return false;
value.push_back(conv.operator typename value_conv::template cast_op_type<Value>()); value.push_back(cast_op<Value>(conv));
} }
return true; return true;
} }
@ -169,7 +167,7 @@ template <typename Type, size_t Size> struct type_caster<std::array<Type, Size>>
for (auto it : l) { for (auto it : l) {
if (!conv.load(it, convert)) if (!conv.load(it, convert))
return false; return false;
value[ctr++] = conv.operator typename value_conv::template cast_op_type<Type>(); value[ctr++] = cast_op<Type>(conv);
} }
return true; return true;
} }
@ -221,7 +219,7 @@ template<typename T> struct optional_caster {
if (!inner_caster.load(src, convert)) if (!inner_caster.load(src, convert))
return false; return false;
value.emplace(inner_caster.operator typename value_conv::template cast_op_type<typename T::value_type>()); value.emplace(cast_op<typename T::value_type>(inner_caster));
return true; return true;
} }