Merge pull request #269 from jagerman/ternary-description

 Add _<bool>("s1", "s2") ternary & use TYPE_CASTER
diff --git a/include/pybind11/cast.h b/include/pybind11/cast.h
index 4f7bc2d..a2a135e 100644
--- a/include/pybind11/cast.h
+++ b/include/pybind11/cast.h
@@ -369,22 +369,7 @@
         }
     }
 
-    static handle cast(const T *src, return_value_policy policy, handle parent) {
-        return cast(*src, policy, parent);
-    }
-
-    template <typename T2 = T, typename std::enable_if<std::is_integral<T2>::value, int>::type = 0>
-    static PYBIND11_DESCR name() { return type_descr(_("int")); }
-
-    template <typename T2 = T, typename std::enable_if<!std::is_integral<T2>::value, int>::type = 0>
-    static PYBIND11_DESCR name() { return type_descr(_("float")); }
-
-    operator T*() { return &value; }
-    operator T&() { return value; }
-
-    template <typename T2> using cast_op_type = pybind11::detail::cast_op_type<T2>;
-protected:
-    T value;
+    PYBIND11_TYPE_CASTER(T, _<std::is_integral<T>::value>("int", "float"));
 };
 
 template <> class type_caster<void_type> {
diff --git a/include/pybind11/descr.h b/include/pybind11/descr.h
index 6c1d864..0104e2b 100644
--- a/include/pybind11/descr.h
+++ b/include/pybind11/descr.h
@@ -83,6 +83,16 @@
     static constexpr auto digits = descr<sizeof...(Digits), 0>({ ('0' + Digits)..., '\0' }, { nullptr });
 };
 
+// Ternary description (like std::conditional)
+template <bool B, size_t Size1, size_t Size2>
+constexpr typename std::enable_if<B, descr<Size1 - 1, 0>>::type _(char const(&text1)[Size1], char const(&)[Size2]) {
+    return _(text1);
+}
+template <bool B, size_t Size1, size_t Size2>
+constexpr typename std::enable_if<!B, descr<Size2 - 1, 0>>::type _(char const(&)[Size1], char const(&text2)[Size2]) {
+    return _(text2);
+}
+
 template <size_t Size> auto constexpr _() {
     return int_to_str<Size / 10, Size % 10>::digits;
 }
@@ -153,6 +163,9 @@
     return descr(text, types);
 }
 
+template <bool B> PYBIND11_NOINLINE typename std::enable_if<B, descr>::type _(const char *text1, const char *) { return _(text1); }
+template <bool B> PYBIND11_NOINLINE typename std::enable_if<!B, descr>::type _(char const *, const char *text2) { return _(text2); }
+
 template <typename Type> PYBIND11_NOINLINE descr _() {
     const std::type_info *types[2] = { &typeid(Type), nullptr };
     return descr("%", types);
diff --git a/include/pybind11/eigen.h b/include/pybind11/eigen.h
index ecad2d5..7a0fe93 100644
--- a/include/pybind11/eigen.h
+++ b/include/pybind11/eigen.h
@@ -99,10 +99,6 @@
         return true;
     }
 
-    static handle cast(const Type *src, return_value_policy policy, handle parent) {
-        return cast(*src, policy, parent);
-    }
-
     static handle cast(const Type &src, return_value_policy /* policy */, handle /* parent */) {
         if (isVector) {
             return array(buffer_info(
@@ -139,15 +135,8 @@
         }
     }
 
-    template <typename _T> using cast_op_type = pybind11::detail::cast_op_type<_T>;
-
-    static PYBIND11_DESCR name() {
-        return _("numpy.ndarray[dtype=") + npy_format_descriptor<Scalar>::name() +
-               _(", shape=(") + rows() + _(", ") + cols() + _(")]");
-    }
-
-    operator Type*() { return &value; }
-    operator Type&() { return value; }
+    PYBIND11_TYPE_CASTER(Type, _("numpy.ndarray[dtype=") + npy_format_descriptor<Scalar>::name() +
+            _(", shape=(") + rows() + _(", ") + cols() + _(")]"));
 
 protected:
     template <typename T = Type, typename std::enable_if<T::RowsAtCompileTime == Eigen::Dynamic, int>::type = 0>
@@ -158,9 +147,6 @@
     static PYBIND11_DESCR cols() { return _("n"); }
     template <typename T = Type, typename std::enable_if<T::ColsAtCompileTime != Eigen::Dynamic, int>::type = 0>
     static PYBIND11_DESCR cols() { return _<T::ColsAtCompileTime>(); }
-
-protected:
-    Type value;
 };
 
 template<typename Type>
@@ -214,10 +200,6 @@
         return true;
     }
 
-    static handle cast(const Type *src, return_value_policy policy, handle parent) {
-        return cast(*src, policy, parent);
-    }
-
     static handle cast(const Type &src, return_value_policy /* policy */, handle /* parent */) {
         const_cast<Type&>(src).makeCompressed();
 
@@ -275,18 +257,8 @@
         ).release();
     }
 
-    template <typename _T> using cast_op_type = pybind11::detail::cast_op_type<_T>;
-
-    template <typename T = Type, typename std::enable_if<(T::Flags & Eigen::RowMajorBit) != 0, int>::type = 0>
-    static PYBIND11_DESCR name() { return _("scipy.sparse.csr_matrix[dtype=") + npy_format_descriptor<Scalar>::name() + _("]"); }
-    template <typename T = Type, typename std::enable_if<(T::Flags & Eigen::RowMajorBit) == 0, int>::type = 0>
-    static PYBIND11_DESCR name() { return _("scipy.sparse.csc_matrix[dtype=") + npy_format_descriptor<Scalar>::name() + _("]"); }
-
-    operator Type*() { return &value; }
-    operator Type&() { return value; }
-
-protected:
-    Type value;
+    PYBIND11_TYPE_CASTER(Type, _<(Type::Flags & Eigen::RowMajorBit) != 0>("scipy.sparse.csr_matrix[dtype=", "scipy.sparse.csc_matrix[dtype=")
+            + npy_format_descriptor<Scalar>::name() + _("]"));
 };
 
 NAMESPACE_END(detail)