modularized logic in preceding change, fixed issue with char (fixes #150)
diff --git a/example/issues.cpp b/example/issues.cpp
index e8cf831..1a4fc31 100644
--- a/example/issues.cpp
+++ b/example/issues.cpp
@@ -15,4 +15,7 @@
 
     // #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 64bd7c6..8628439 100644
--- a/example/issues.py
+++ b/example/issues.py
@@ -3,6 +3,7 @@
 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 6f672ff..4e02121 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 5bc1a67..dddd40a 100644
--- a/include/pybind11/cast.h
+++ b/include/pybind11/cast.h
@@ -197,6 +197,12 @@
     object temp;
 };
 
+/* Determine suitable casting operator */
+template <typename T>
+using cast_op_type = typename std::conditional<std::is_pointer<T>::value,
+    typename std::add_pointer<typename intrinsic_type<T>::type>::type,
+    typename std::add_lvalue_reference<typename intrinsic_type<T>::type>::type>::type;
+
 /// Generic type caster for objects stored on the heap
 template <typename type, typename Enable = void> class type_caster : public type_caster_generic {
 public:
@@ -214,6 +220,8 @@
         return type_caster_generic::cast(src, policy, parent, &typeid(type), &copy_constructor);
     }
 
+    template <typename T> using cast_op_type = pybind11::detail::cast_op_type<T>;
+
     operator type*() { return (type *) value; }
     operator type&() { return *((type *) value); }
 protected:
@@ -234,7 +242,8 @@
             return cast(*src, policy, parent); \
         } \
         operator type*() { return &value; } \
-        operator type&() { return value; }
+        operator type&() { return value; } \
+        template <typename _T> 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 @@
     operator T*() { return &value; }
     operator T&() { return value; }
 
+    template <typename T2> using cast_op_type = pybind11::detail::cast_op_type<T2>;
 protected:
     T value;
 };
@@ -348,7 +358,7 @@
 
     operator void *() { return value; }
 private:
-    void *value;
+    void *value = nullptr;
 };
 
 template <> class type_caster<std::nullptr_t> : public type_caster<void_type> { };
@@ -442,6 +452,9 @@
     operator char*() { return (char *) value.c_str(); }
     operator char() { if (value.length() > 0) return value[0]; else return '\0'; }
 
+    template <typename T>
+    using cast_op_type = typename std::conditional<std::is_pointer<T>::value, char*, char>::type;
+
     static PYBIND11_DESCR name() { return type_descr(_(PYBIND11_STRING_NAME)); }
 };
 
@@ -489,6 +502,8 @@
             _(", ") + type_caster<typename intrinsic_type<T2>::type>::name() + _(")"));
     }
 
+    template <typename T> using cast_op_type = type;
+
     operator type() {
         return type(first, second);
     }
@@ -526,29 +541,21 @@
         return void_type();
     }
 
+    template <typename T> using cast_op_type = type;
+
     operator type() {
         return cast(typename make_index_sequence<sizeof...(Tuple)>::type());
     }
 
 protected:
-    template <typename T> /* Used to select the right casting operator in the two functions below */
-    using cast_target =
-        typename std::conditional<
-            is_specialization_of<typename intrinsic_type<T>::type, std::tuple>::value ||
-            is_specialization_of<typename intrinsic_type<T>::type, std::pair>::value,
-            typename intrinsic_type<T>::type, /* special case: tuple/pair -> pass by value */
-            typename std::conditional<
-                std::is_pointer<T>::value,
-                typename std::add_pointer<typename intrinsic_type<T>::type>::type, /* pass using pointer */
-                typename std::add_lvalue_reference<typename intrinsic_type<T>::type>::type /* pass using reference */
-            >::type>;
-
     template <typename ReturnValue, typename Func, size_t ... Index> ReturnValue call(Func &&f, index_sequence<Index...>) {
-        return f(std::get<Index>(value).operator typename cast_target<Tuple>::type()...);
+        return f(std::get<Index>(value)
+            .operator typename type_caster<typename intrinsic_type<Tuple>::type>::template cast_op_type<Tuple>()...);
     }
 
     template <size_t ... Index> type cast(index_sequence<Index...>) {
-        return type(std::get<Index>(value).operator typename cast_target<Tuple>::type()...);
+        return type(std::get<Index>(value)
+            .operator typename type_caster<typename intrinsic_type<Tuple>::type>::template cast_op_type<Tuple>()...);
     }
 
     template <size_t ... Indices> bool load(handle src, bool convert, index_sequence<Indices...>) {