[FR] Eigen Type Traits Header

Describe the feature you would like to be implemented.

I'd like to propose adding an Eigen/TypeTraits header that can be used to detect traits of a given Eigen object. For background, the Stan math library has a bunch of these traits we can easily backport for other users of the Eigen library (see here for a bunch of them). Below is a godbolt with a minimal example we can apply to Eigen's inheritance schema for detecting whether a type inherits from one of Eigen's base types.

https://godbolt.org/z/cc3YWMz11

So there can be type traits such as

is_eigen_base_derived
is_eigen_array_base_derive
is_eigen_matrix_base_derived
is_eigen_dense_base_derived
is_eigen_map_base_derived

We also use these type traits for finding an Eigen expressions PlainType (see here), determining whether an expression is a view or contains computation that needs evaluated (like ref, see here), and simpler things such as checking whether we are working with row/column vectors.

Would such a feature be useful for other users? Why?

I think so! I'll list some examples below of how we use these in the Stan math library.

In Stan we do some wacky stuff by passing in Eigen expressions to functions which means we need a lot of stuff to make sure that's safe. But some nice places we use these are for functions like to_ref() which takes in an eigen object and if it's an expression that's not a view it evals the object. This is nice because it's essentially the Ref<> class but you can use stuff like auto&& B = to_ref(A). We also use these for our meta requires type traits that allow for a "legacy style" requires in C++11 such as in the below godbolt.

https://godbolt.org/z/PhrdYceEW

idk if Eigen would want something like that, but they are quite nice. They look a bit weird, but the main trick is that since enable_if gives back a void by default. When the bool is true we have a Non-Type Template Parameter of type void* set to a default value of nullptr. When the bool is false the template is malformed and we have good ol' SFINAE to kick the function out of the list of possible functions to use. We have a ton of these requires in the library and use a macro to generate them based on the type traits (see here). The macro also generates docs for each which is nice.

Another place we use these type traits in our library is deciding when to copy an object to our arena allocator. If a user passes us a type derived from Eigen::Map and it's ref_type<> and itself are the same (aka it does not need to be evaluated) we don't actually copy the memory and assume the user will keep that Eigen Map alive until it's no longer needed.

Any hints on how to implement the requested feature?

What I'm proposing is mostly a backport of Stan's type traits related to Eigen to an actual Eigen header. I can do this and can support maintaining it (since I maintain these in Stan math we can just switch over to using the Eigen ones once they are in so there's no real burden on me). The only slight note that makes this more than a straight copy paste is that Stan uses c++14, which means some things from C++14 would need to be backported to Eigen.

Additional resources

Happy to answer any questions! If there is interest in this I would be happy to write out something like a design doc to flesh everything out in more detail.