I trying do write a C++ template-class which should be able to deal with "simple" types and with "Eigen::MatrixBase"-like types via the same interface. I manage to get thie desired behavior with two different simple types, but struggle to squeeze the Eigen-syntax into my minimal-example... Maybe someone can give me an advice?
While looking around, this comes close to what i wanna have -- without Eigen. This looks similar as well.
#ifndef __MINIMAL_H__
#define __MINIMAL_H__
#include <Eigen/Core>
// base-class defining and interface + common functions
// child-classes with possible overloads. does not work to
// define basic eigen-types as template specialization parameter
template<typename T>
class MinimalBase
{
public:
MinimalBase(const T& val)
:val(val){};
T val;
// pure virtual interface
virtual void setZero() = 0;
// the common functionality
void increase() { val = val*6; };
void decrease() { val = val/7; };
};
// again pure virtual, so that the compiler will not instantiate this when
// trying to deduce the correct template specialization
template<typename T>
class Minimal : public MinimalBase<T>
{
public:
Minimal(const T& val)
:MinimalBase<T>(val){};
virtual void setZero() = 0;
// the rest of the common functionality is inherited from MinimalBase
};
// one spezialization for "int"
template<>
class Minimal<int> : public MinimalBase<int>
{
public:
Minimal()
:MinimalBase<int>(4){};
virtual void setZero() { val = 0; };
};
// this one is actually shorter...
template<>
class Minimal<short> : public MinimalBase<short>
{
public:
Minimal()
:MinimalBase<short>(1){};
virtual void setZero() { val = 0; };
void increase() { val = val*3; };
};
// and the eigen-one (at best limited to vector-like matrices)... how to do this?
template<class Derived>
class Minimal<Eigen::MatrixBase<Derived> > : public MinimalBase<Eigen::MatrixBase<Derived> >
{
public:
Minimal<Eigen::MatrixBase<Derived> >()
:MinimalBase<Eigen::MatrixBase<Derived> >(Eigen::MatrixBase<Derived>::Zero()){};
virtual void setZero() { this->val.setZero(); };
};
#endif
The last block, with the Eigen stuff, does not compile. I'm more lost in the general direction how to solve this, the specific syntax is not clear to me. Using this header the following lines will not compile in your generic minimal-example-main-cpp (short of the Eigen-stuff):
Minimal<int>A;
Minimal<short>B;
// this does not work:
Minimal<Eigen::Vector2f>C;
std::cerr << "before: " << A.val << " " << B.val << "
";
A.increase();
A.decrease();
B.increase();
B.setZero()
std::cerr << "after: " << A.val << " " << B.val << "
";
The Compiler error message looks like this:
/home/joe/test/test.cpp: In function ‘int main()’:
/home/joe/test/test.cpp:36:29: error: no matching function for call to ‘Minimal<Eigen::Matrix<float, 2, 1> >::Minimal()’
Minimal<Eigen::Vector2f>C;
^
/home/joe/test/test.cpp:36:29: note: candidates are:
In file included from /home/joe/test/test.cpp:7:0:
/home/joe/test/minimal.h:26:9: note: Minimal<T>::Minimal(const T&) [with T = Eigen::Matrix<float, 2, 1>]
Minimal(const T& val)
^
/home/joe/test/minimal.h:26:9: note: candidate expects 1 argument, 0 provided
/home/joe/test/minimal.h:23:7: note: Minimal<Eigen::Matrix<float, 2, 1> >::Minimal(const Minimal<Eigen::Matrix<float, 2, 1> >&)
class Minimal : public MinimalBase<T>
^
/home/joe/test/minimal.h:23:7: note: candidate expects 1 argument, 0 provided
/home/joe/test/test.cpp:36:29: error: cannot declare variable ‘C’ to be of abstract type ‘Minimal<Eigen::Matrix<float, 2, 1> >’
Minimal<Eigen::Vector2f>C;
^
In file included from /home/joe/test/test.cpp:7:0:
/home/joe/test/minimal.h:23:7: note: because the following virtual functions are pure within ‘Minimal<Eigen::Matrix<float, 2, 1> >’:
class Minimal : public MinimalBase<T>
^
/home/joe/test/minimal.h:29:22: note: void Minimal<T>::setZero() [with T = Eigen::Matrix<float, 2, 1>]
virtual void setZero() = 0;
^
Edit: The resulting minimal-example demonstration finally found its way to github
See Question&Answers more detail:
os 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…