mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-11 08:03:55 +00:00
Merge pull request #427 from dean0x7d/eigen-bases
Simplify base class detection for Eigen types
This commit is contained in:
commit
5699986d12
@ -390,6 +390,21 @@ template <template<class> class Predicate, class Default, class... T> using firs
|
||||
template <typename T, typename... /*Us*/> struct deferred_type { using type = T; };
|
||||
template <typename T, typename... Us> using deferred_t = typename deferred_type<T, Us...>::type;
|
||||
|
||||
template <template<typename...> class Base>
|
||||
struct is_template_base_of_impl {
|
||||
template <typename... Us> static std::true_type check(Base<Us...> *);
|
||||
static std::false_type check(...);
|
||||
};
|
||||
|
||||
/// Check if a template is the base of a type. For example:
|
||||
/// `is_template_base_of<Base, T>` is true if `struct T : Base<U> {}` where U can be anything
|
||||
template <template<typename...> class Base, typename T>
|
||||
#if !defined(_MSC_VER)
|
||||
using is_template_base_of = decltype(is_template_base_of_impl<Base>::check((T*)nullptr));
|
||||
#else // MSVC2015 has trouble with decltype in template aliases
|
||||
struct is_template_base_of : decltype(is_template_base_of_impl<Base>::check((T*)nullptr)) { };
|
||||
#endif
|
||||
|
||||
/// Ignore that a variable is unused in compiler warnings
|
||||
inline void ignore_unused(const int *) { }
|
||||
|
||||
|
@ -34,47 +34,18 @@
|
||||
NAMESPACE_BEGIN(pybind11)
|
||||
NAMESPACE_BEGIN(detail)
|
||||
|
||||
template <typename T> class is_eigen_dense {
|
||||
private:
|
||||
template<typename Derived> static std::true_type test(const Eigen::DenseBase<Derived> &);
|
||||
static std::false_type test(...);
|
||||
public:
|
||||
static constexpr bool value = decltype(test(std::declval<T>()))::value;
|
||||
};
|
||||
|
||||
// Eigen::Ref<Derived> satisfies is_eigen_dense, but isn't constructible, so it needs a special
|
||||
// type_caster to handle argument copying/forwarding.
|
||||
template <typename T> class is_eigen_ref {
|
||||
private:
|
||||
template<typename Derived> static enable_if_t<
|
||||
std::is_same<typename std::remove_const<T>::type, Eigen::Ref<Derived>>::value,
|
||||
Derived> test(const Eigen::Ref<Derived> &);
|
||||
static void test(...);
|
||||
public:
|
||||
typedef decltype(test(std::declval<T>())) Derived;
|
||||
static constexpr bool value = !std::is_void<Derived>::value;
|
||||
};
|
||||
|
||||
template <typename T> class is_eigen_sparse {
|
||||
private:
|
||||
template<typename Derived> static std::true_type test(const Eigen::SparseMatrixBase<Derived> &);
|
||||
static std::false_type test(...);
|
||||
public:
|
||||
static constexpr bool value = decltype(test(std::declval<T>()))::value;
|
||||
};
|
||||
template <typename T> using is_eigen_dense = is_template_base_of<Eigen::DenseBase, T>;
|
||||
template <typename T> using is_eigen_sparse = is_template_base_of<Eigen::SparseMatrixBase, T>;
|
||||
template <typename T> using is_eigen_ref = is_template_base_of<Eigen::RefBase, T>;
|
||||
|
||||
// Test for objects inheriting from EigenBase<Derived> that aren't captured by the above. This
|
||||
// basically covers anything that can be assigned to a dense matrix but that don't have a typical
|
||||
// matrix data layout that can be copied from their .data(). For example, DiagonalMatrix and
|
||||
// SelfAdjointView fall into this category.
|
||||
template <typename T> class is_eigen_base {
|
||||
private:
|
||||
template<typename Derived> static std::true_type test(const Eigen::EigenBase<Derived> &);
|
||||
static std::false_type test(...);
|
||||
public:
|
||||
static constexpr bool value = !is_eigen_dense<T>::value && !is_eigen_sparse<T>::value &&
|
||||
decltype(test(std::declval<T>()))::value;
|
||||
};
|
||||
template <typename T> using is_eigen_base = bool_constant<
|
||||
is_template_base_of<Eigen::EigenBase, T>::value
|
||||
&& !is_eigen_dense<T>::value && !is_eigen_sparse<T>::value
|
||||
>;
|
||||
|
||||
template<typename Type>
|
||||
struct type_caster<Type, enable_if_t<is_eigen_dense<Type>::value && !is_eigen_ref<Type>::value>> {
|
||||
@ -159,10 +130,13 @@ protected:
|
||||
static PYBIND11_DESCR cols() { return _<T::ColsAtCompileTime>(); }
|
||||
};
|
||||
|
||||
template<typename Type>
|
||||
struct type_caster<Type, enable_if_t<is_eigen_dense<Type>::value && is_eigen_ref<Type>::value>> {
|
||||
// Eigen::Ref<Derived> satisfies is_eigen_dense, but isn't constructable, so it needs a special
|
||||
// type_caster to handle argument copying/forwarding.
|
||||
template <typename CVDerived, int Options, typename StrideType>
|
||||
struct type_caster<Eigen::Ref<CVDerived, Options, StrideType>> {
|
||||
protected:
|
||||
using Derived = typename std::remove_const<typename is_eigen_ref<Type>::Derived>::type;
|
||||
using Type = Eigen::Ref<CVDerived, Options, StrideType>;
|
||||
using Derived = typename std::remove_const<CVDerived>::type;
|
||||
using DerivedCaster = type_caster<Derived>;
|
||||
DerivedCaster derived_caster;
|
||||
std::unique_ptr<Type> value;
|
||||
|
Loading…
Reference in New Issue
Block a user