Merge pull request #427 from dean0x7d/eigen-bases

Simplify base class detection for Eigen types
This commit is contained in:
Wenzel Jakob 2016-09-29 21:20:26 +02:00 committed by GitHub
commit 5699986d12
2 changed files with 28 additions and 39 deletions

View File

@ -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 *) { }

View File

@ -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;