Copy templated function argument in Eigen

eigen matrix
eigen::ref
eigen pass by reference
eigen return matrix from function
eigen::block
eigen::map
eigen vector template
copy eigen matrix

I am writing a generic class that utilizes Eigen data types. I already have problems assigning constructor arguments to class member variables. A simplified version of my code would be:

template <typename Derived>
class A
{
public:
  Eigen::Matrix<Derived> M; // error C2976: too few template parameters

A(const Eigen::DenseBase<Derived> & V)
{
  M = V.eval(); // I would want to snapshot the value of V.
}
};

My question is now what data type M should be? I tried a variety of options, such as:

Eigen::internal::plain_matrix_type_column_major<Derived> M;
Eigen::DenseBase<Derived> M;

but they just generate different errors. Note that I use C++17 and expect the class template parameter to be inferred from the constructor.

Your container needs the actual "plain type" as template argument:

template <typename PlainType>
class A
{
    PlainType M; 
public:
    template<class Derived>
    A(const Eigen::MatrixBase<Derived> & V) : M(V) {}
};

And you need an additional template deduction rule:

template<class Derived>
A(const Eigen::MatrixBase<Derived> & V) -> A<typename Derived::PlainObject>;

Usage example (on godbolt):

template<class X>
void bar(X&); // just to read full type of A

void foo(Eigen::Matrix2d const& M)
{
    A a = M*M;
    bar(a);  // calls bar<A<Matrix2d>>();
}

Writing Functions Taking Eigen Types as Parameters, By letting your function take templated parameters of these base types, you can and still keep some level of genericity to avoid stupid copies of the arguments. Eigen's use of expression templates results in potentially every expression being of a different type. If you pass such an expression to a function taking a parameter of type Matrix, your expression will implicitly be evaluated into a temporary Matrix, which will then be passed to the function.

The declaration of the Eigen::Matrix variable M should be something like:

Eigen::Matrix<typename Derived::Scalar, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> M; 

Then your code will compile. See Demo.

The detailed description of each of the template parameters can be found at this link.

The template and typename keywords in C++, topLeftCorner(3,3) as the parameter src , then this is copied into a temporary variable of type MatrixXf; this copy can be avoided. As explained in Writing Functions� template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols> class Eigen::Matrix< _Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols > The matrix class, also used for vectors and row-vectors. The Matrix class is the work-horse for all dense matrices and vectors within Eigen. Vectors are matrices with one column

A generic way of declaring your type would be to use the declaration generating it as a source, this way you don't have to look at specific ways to declare complicated template types, this is an example based on your code:

decltype(static_cast<Eigen::DenseBase<Derived> *>(nullptr)->eval()) M;

don't worry there is no nullptr dereference here because the code inside decltype is not executed.

As pointed in the comments there's a cleaner way of writing this:

decltype(declval<Eigen::DenseBase<Derived>>().eval()) M;

and if you're worried that the type might be a reference and don't want that:

remove_reference_t<decltype(declval<Eigen::DenseBase<Derived>>().eval())> M;

also don't forget to #include <type_traits> and either prefix everything with std:: or add using namespace std; to your code.

To make the syntax simpler for future use add this to the beginning of your code:

template<typename T, typename T::f>
using member_function_return_t = remove_reference_t<decltype(declval<T>().f())>;

and than declare the variable as:

member_function_return_t<Eigen::DenseBase<Derived>, Eigen::DenseBase<Derived>::eval> M;

Eigen::Ref< PlainObjectType, Options, StrideType > Class , This class provides a way to write non-template functions taking Eigen objects as parameters while limiting the number of copies. A Ref<> object can represent� In order to instantiate a function template, every template argument must be known, but not every template argument has to be specified. When possible, the compiler will deduce the missing template arguments from the function arguments. This occurs when a function call is attempted and when an address of a function template is taken.

eigen/Cookbook, Eigen mostly achieves a pleasantly readable mathematical syntax, but quirks of the Some member functions of these matrix types have template parameters of 11 12 // Copy constructor from any Eigen matrix type 13 template<typename� This class provides a way to write non-template functions taking Eigen objects as parameters while limiting the number of copies. A Ref<> object can represent either a const expression or a l-value: A Ref<> object can represent either a const expression or a l-value:

[PDF] C++ tutorial, Template metaprogramming. ▷ STL containers. ▷ C++11. ▷ Eigen. C++ tutorial inside function. No copy is performed. This is valid in C++ and called function overloading. taking 2 arguments and returning the minimum. template� To unpack a parameter pack, use a templated function taking one (or more) parameters explicitly, and the ‘rest’ of the parameters as a template parameter pack. Recurse towards a base case: call your recursive function with the ‘rest…’ arguments, and let the compiler unpack your parameters in subsequent calls to your recursive function.

Eliminating temporary values & allocations via Eigen template , Eliminating temporary values & allocations via Eigen template expressions or Eigen::Ref Some of our function arguments could be more agressively templated. early and therefore copy too much when dealing with expression templated. The main reason to do something like this is to specialize void integerA(int x) to do something else. That is, if the programmer provides as input argument an int to member function abc::integerA then because of the C++ rules instead of instantiating the template member function the compiler would pick

Comments
  • 'too few template parameters' – if Eigen::Matrix appears to be correct type for you, then stay with, but find out what the other parameters are used for and apply them appropriately (hint: you might need further template parameters for your own class, too).
  • How do you intend to use A? What types can Derived have? You could try Derived::PlainObject, if you want to store any Derived type in the corresponding plain type (this automatically derives the scalar type, dimensions, etc).
  • I expect Derived to by a dense Matrix/Array. V can have fixed, dynamic, or mixed sizes. M is intended to just store the values of V, which is the reason for the .eval(). In general, A will compute new values based on V but I need to keep the input and other intermediate results for later use.
  • Can you post a minimal reproducible example of how you intend to use A? I guess you essentially want to write A a{some_expression};, right?
  • This is certainly possible but what would happen if the input matrix is fixed size? I assume that this information would get lost when making everything dynamic.
  • You can also specify integer values instead of Eigen::Dynamic. See: godbolt.org/z/JztB4N
  • This would be the clearest way to do it if the Matrix size is known when the class is constructed. In my case, I intend to write a class that can take both fixed size and dynamic arguments. I cannot enforce certain matrix sizes when writing the class.
  • You can use Derived::RowsAtCompileTime, etc. But then you could also simply use typename Derived::PlainObject or typename Derived::PlainMatrix.
  • I tested this and it seems to work. I was not aware of this methodology. I was hoping that Eigen provides something more straightforward to obtain the type of a matrix or an expression.
  • If Derived is already of Matrix type, this will result in a const-reference to the type (which may or may not what the OP wants).
  • I believe std::declval was introduced to avoid such constructs ;)
  • included both your observations in the answer
  • Honestly, I don't see any advantage vs just writing typename Derived::PlainObject M.