Search code examples
eigen3

Distinguish at runtime between an Eigen Array and an Eigen Matrix


Is there a way to distinguish at runtime between an Eigen Array and an Eigen Matrix? For example,

template<typename Derived>
void foo( Eigen::EigenBase<Derived>& base )
{
if( /* base is an Eigen::Matrix */ )
{
   // do something
}
else // base is an Eigen::Array
{
   // do something else
}
}

I could write the function with two different signatures, e.g.

template<typename Derived>
void foo( Eigen::ArrayBase<Derived>& base )
{
}

and

template<typename Derived>
void foo( Eigen::MatrixBase<Derived>& base )
{
}

Having just one function would help avoid clutter.


Solution

  • You can check using std::is_base_of if Derived inherits from MatrixBase or ArrayBase:

    template <typename Derived>
    void foo(Eigen::EigenBase<Derived> const&  base) {
        if (std::is_base_of<Eigen::MatrixBase<Derived>, Derived>::value) {
            fooMatrix();
        } else if (std::is_base_of<Eigen::ArrayBase<Derived>, Derived>::value) {
            fooArray();
        }
    }
    

    With C++17 or later you can use an if constexpr branch for that (and use std::is_base_of_v for brevity). This allows to write code into the branches which would not compile with the opposite type.

    template <typename Derived>
    void foo(Eigen::EigenBase<Derived> const&  base) {
        if constexpr (std::is_base_of_v<Eigen::MatrixBase<Derived>, Derived>) {
            fooMatrix();
        } else if constexpr (std::is_base_of_v<Eigen::ArrayBase<Derived>, Derived>) {
            fooArray();
        }
    }
    

    The second method is guaranteed to be checked at compile-time, the first one is not (but an optimizing compiler will still only produce code for the true-branch).