From d3349af48b0ffa101660b370bc702454fd064968 Mon Sep 17 00:00:00 2001 From: Wenzel Jakob Date: Sat, 26 Mar 2016 23:04:10 +0100 Subject: [PATCH] modularized logic in preceding change, fixed issue with char (fixes #150) --- example/issues.cpp | 3 +++ example/issues.py | 3 ++- example/issues.ref | 1 + include/pybind11/cast.h | 39 +++++++++++++++++++++++---------------- 4 files changed, 29 insertions(+), 17 deletions(-) diff --git a/example/issues.cpp b/example/issues.cpp index e8cf831fb..1a4fc31a0 100644 --- a/example/issues.cpp +++ b/example/issues.cpp @@ -15,4 +15,7 @@ void init_issues(py::module &m) { // #137: const char* isn't handled properly m2.def("print_cchar", [](const char *string) { std::cout << string << std::endl; }); + + // #150: char bindings broken + m2.def("print_char", [](char c) { std::cout << c << std::endl; }); } diff --git a/example/issues.py b/example/issues.py index 64bd7c62a..8628439e7 100644 --- a/example/issues.py +++ b/example/issues.py @@ -3,6 +3,7 @@ from __future__ import print_function import sys sys.path.append('.') -from example.issues import print_cchar +from example.issues import print_cchar, print_char print_cchar("const char *") +print_char('c') diff --git a/example/issues.ref b/example/issues.ref index 6f672fffe..4e021217f 100644 --- a/example/issues.ref +++ b/example/issues.ref @@ -1 +1,2 @@ const char * +c diff --git a/include/pybind11/cast.h b/include/pybind11/cast.h index 5bc1a679d..dddd40a2c 100644 --- a/include/pybind11/cast.h +++ b/include/pybind11/cast.h @@ -197,6 +197,12 @@ protected: object temp; }; +/* Determine suitable casting operator */ +template +using cast_op_type = typename std::conditional::value, + typename std::add_pointer::type>::type, + typename std::add_lvalue_reference::type>::type>::type; + /// Generic type caster for objects stored on the heap template class type_caster : public type_caster_generic { public: @@ -214,6 +220,8 @@ public: return type_caster_generic::cast(src, policy, parent, &typeid(type), ©_constructor); } + template using cast_op_type = pybind11::detail::cast_op_type; + operator type*() { return (type *) value; } operator type&() { return *((type *) value); } protected: @@ -234,7 +242,8 @@ protected: return cast(*src, policy, parent); \ } \ operator type*() { return &value; } \ - operator type&() { return value; } + operator type&() { return value; } \ + template using cast_op_type = pybind11::detail::cast_op_type<_T>; #define PYBIND11_DECLARE_HOLDER_TYPE(type, holder_type) \ namespace pybind11 { namespace detail { \ @@ -310,6 +319,7 @@ public: operator T*() { return &value; } operator T&() { return value; } + template using cast_op_type = pybind11::detail::cast_op_type; protected: T value; }; @@ -348,7 +358,7 @@ public: operator void *() { return value; } private: - void *value; + void *value = nullptr; }; template <> class type_caster : public type_caster { }; @@ -442,6 +452,9 @@ public: operator char*() { return (char *) value.c_str(); } operator char() { if (value.length() > 0) return value[0]; else return '\0'; } + template + using cast_op_type = typename std::conditional::value, char*, char>::type; + static PYBIND11_DESCR name() { return type_descr(_(PYBIND11_STRING_NAME)); } }; @@ -489,6 +502,8 @@ public: _(", ") + type_caster::type>::name() + _(")")); } + template using cast_op_type = type; + operator type() { return type(first, second); } @@ -526,29 +541,21 @@ public: return void_type(); } + template using cast_op_type = type; + operator type() { return cast(typename make_index_sequence::type()); } protected: - template /* Used to select the right casting operator in the two functions below */ - using cast_target = - typename std::conditional< - is_specialization_of::type, std::tuple>::value || - is_specialization_of::type, std::pair>::value, - typename intrinsic_type::type, /* special case: tuple/pair -> pass by value */ - typename std::conditional< - std::is_pointer::value, - typename std::add_pointer::type>::type, /* pass using pointer */ - typename std::add_lvalue_reference::type>::type /* pass using reference */ - >::type>; - template ReturnValue call(Func &&f, index_sequence) { - return f(std::get(value).operator typename cast_target::type()...); + return f(std::get(value) + .operator typename type_caster::type>::template cast_op_type()...); } template type cast(index_sequence) { - return type(std::get(value).operator typename cast_target::type()...); + return type(std::get(value) + .operator typename type_caster::type>::template cast_op_type()...); } template bool load(handle src, bool convert, index_sequence) {