diff --git a/include/pybind11/cast.h b/include/pybind11/cast.h index 0c862e4be..e356a02f1 100644 --- a/include/pybind11/cast.h +++ b/include/pybind11/cast.h @@ -39,6 +39,15 @@ class type_caster : public type_caster_base {}; template using make_caster = type_caster>; +template +struct is_generic_type>::value>> + : public std::true_type {}; + +template +struct is_generic_type>::value>> + : public std::false_type {}; + // Shortcut for calling a caster's `cast_op_type` cast operator for casting a type_caster to a T template typename make_caster::template cast_op_type cast_op(make_caster &caster) { diff --git a/include/pybind11/pytypes.h b/include/pybind11/pytypes.h index 1e76d7bc1..d0e279c64 100644 --- a/include/pybind11/pytypes.h +++ b/include/pybind11/pytypes.h @@ -48,6 +48,11 @@ PYBIND11_NAMESPACE_BEGIN(detail) class args_proxy; bool isinstance_generic(handle obj, const std::type_info &tp); +// Indicates that type is generic and and does not have a specialized +// `type_caster<>` specialization. Defined in `cast.h`. +template +struct is_generic_type; + // Accessor forward declarations template class accessor; @@ -836,7 +841,7 @@ inline void raise_from(error_already_set &err, PyObject *type, const char *messa /** \ingroup python_builtins \rst Return true if ``obj`` is an instance of ``T``. Type ``T`` must be a subclass of - `object` or a class which was exposed to Python as ``py::class_``. + `object` or a class which was exposed to Python as ``py::class_`` (generic). \endrst */ template ::value, int> = 0> bool isinstance(handle obj) { @@ -845,6 +850,8 @@ bool isinstance(handle obj) { template ::value, int> = 0> bool isinstance(handle obj) { + static_assert(detail::is_generic_type::value, + "isinstance() requires specialization for this type"); return detail::isinstance_generic(obj, typeid(T)); }