The type Eigen::Vector2f
is not equal to Eigen::MatrixBase<Derived>
for any type Derived
. It inherits Eigen::MatrixBase<Eigen::Vector2f>
, but that's not good enough for template specialization matching.
First, let's define a "type trait" that determines whether a type is an Eigen matrix. In C++11:
#include <type_traits>
namespace is_eigen_matrix_detail {
// These functions are never defined.
template <typename T>
std::true_type test(const Eigen::MatrixBase<T>*);
std::false_type test(...);
}
template <typename T>
struct is_eigen_matrix
: public decltype(is_eigen_matrix_detail::test(std::declval<T*>()))
{};
Or in C++03:
namespace is_eigen_matrix_detail {
typedef char yes_type[2];
typedef char no_type[1];
template <typename T>
yes_type test(const Eigen::MatrixBase<T>*);
no_type test(...);
}
template <typename T>
struct is_eigen_matrix {
static const bool value =
(sizeof(is_eigen_matrix_detail::test(static_cast<T*>(0))) ==
sizeof(is_eigen_matrix_detail::yes_type));
};
Then, a standard enable_if
trick can set up a class template specialization that accepts all types and only those types that satisfy the trait.
// Don't bother to define the primary template, and only your
// specializations can ever be used.
template <typename T, typename Enable = void>
class Minimal;
// When not using enable_if tricks, ignore the Enable parameter.
template<>
class Minimal<int> : public MinimalBase<int>
{
// Just as before.
};
// This specialization only exists when T is or inherits an Eigen::MatrixBase
// specialization.
template <typename T>
class Minimal<T, typename std::enable_if<is_eigen_matrix<T>::value>::type>
: public MinimalBase<T>
{
public:
Minimal() : MinimalBase<T>(T::Zero()) {}
virtual void setZero() { this->val.setZero(); }
};
std::enable_if
is C++11. In C++03, either substitute boost::enable_if
or just define and use your own:
template <bool Check, typename T = void>
struct enable_if {};
template <typename T>
struct enable_if<true, T> {
typedef T type;
};