使用 CRTP 创建特征矩阵
Using CRTP to create Eigen matrix
我有一个 classes 的层次结构,其中包含一些特征矩阵作为成员,但它们的大小取决于派生的 class。我希望能够在基 class 中声明矩阵,但使用派生 class 中的大小。我以为我可以为此使用 CRTP,但我不确定我是否正确使用了它。这是我试过的代码
template<typename T>
class Base {
public:
const int matSize = static_cast(T*)(this)->_matSize;
Eigen::Matrix<int, matSize, mastSize> Mat = Eigen::Matrix<int, matSize, matSize>::Zero();
virtual void print() { std::cout << Mat << std::endl; };
};
class Derived1 : public Base<Derived1>{
public:
const int _matSize = 3;
};
class Derived2 : public Base<Derived2>{
public:
const int _matSize = 4;
};
int main(){
Derived1 d1;
d1.print(); // print a 3x3 zero matrix
Derived2 d2;
d2.print(); // print a 4x4 zero matrix
std::cin.get();
return 0;
}
但是,这不起作用。有没有办法实现这样的目标?
编辑:
这样做的主要原因是我有一些函数可以执行一些矩阵代数,无论大小如何。所以我希望能够在不同派生 classes 的对象上调用该函数,并且能够使用相同的函数而不是为每个矩阵大小使用单独的函数。
还有一个接口,任何 Base 类型的对象都将有一个矩阵 Mat,其大小将取决于创建它的 Base 的派生 class。
正如我在评论中所说,确实没有理由仅针对您所指出的内容使用 CRTP,但是如果您出于其他原因设置此模式,则类似以下的内容应该有效(我没有Eigen::Matrix
可用,所以我删除了编译器所需的接口):
#include <iostream>
namespace Eigen {
template<typename T, int W, int H>
class Matrix {
public:
static Matrix<T,W,H> Zero() {
return Matrix<T, W, H>{};
}
std::ostream &print_on(std::ostream &strm) const {
return strm;
}
};
}
template <typename T, int W, int H>
std::ostream &operator<<(std::ostream &strm, Eigen::Matrix<T,W,H> const &matrix) {
return matrix.print_on(strm);
}
template<typename T, int S>
class Base {
public:
Eigen::Matrix<int, S, S> Mat = Eigen::Matrix<int, S, S>::Zero();
virtual void print() { std::cout << Mat << std::endl; };
};
class Derived1 : public Base<Derived1,3>{
public:
};
class Derived2 : public Base<Derived2,4>{
public:
};
template <int Size>
class AdvertisingDerived : public Base<AdvertisingDerived<Size>,Size> {
public:
constexpr static int matrixSize = Size;
};
int main(){
Derived1 d1;
d1.print(); // print a 3x3 zero matrix
Derived2 d2;
d2.print(); // print a 4x4 zero matrix
AdvertisingDerived<3> ad1;
AdvertisingDerived<4> ad2;
std::cin.get();
return 0;
}
您不能访问 Derived1
的成员(从 Derived1
之外的任何地方),直到它被完全定义。此问题的通常解决方法是使用某种特征 class:
template<class D>
struct MyTraits;
template<typename T>
class Base {
public:
static const int matSize = MyTraits<T>::_matSize;
Eigen::Matrix<int, matSize, matSize> Mat = Eigen::Matrix<int, matSize, matSize>::Zero();
virtual void print() { std::cout << Mat << std::endl; };
};
class Derived1;
template<>
struct MyTraits<Derived1> {static const int _matSize = 3;};
class Derived1 : public Base<Derived1>{
public:
};
神马:https://godbolt.org/z/pf-B_R
特别是,如果 Derived1
本身是一个 class 模板,特征也将(部分)模板化。从您提供的代码很难判断这对您的情况是否有意义。
顺便说一句:应该没有必要制作 Base::print()
virtual
。静态多态的要点是避免动态多态。
我有一个 classes 的层次结构,其中包含一些特征矩阵作为成员,但它们的大小取决于派生的 class。我希望能够在基 class 中声明矩阵,但使用派生 class 中的大小。我以为我可以为此使用 CRTP,但我不确定我是否正确使用了它。这是我试过的代码
template<typename T>
class Base {
public:
const int matSize = static_cast(T*)(this)->_matSize;
Eigen::Matrix<int, matSize, mastSize> Mat = Eigen::Matrix<int, matSize, matSize>::Zero();
virtual void print() { std::cout << Mat << std::endl; };
};
class Derived1 : public Base<Derived1>{
public:
const int _matSize = 3;
};
class Derived2 : public Base<Derived2>{
public:
const int _matSize = 4;
};
int main(){
Derived1 d1;
d1.print(); // print a 3x3 zero matrix
Derived2 d2;
d2.print(); // print a 4x4 zero matrix
std::cin.get();
return 0;
}
但是,这不起作用。有没有办法实现这样的目标?
编辑:
这样做的主要原因是我有一些函数可以执行一些矩阵代数,无论大小如何。所以我希望能够在不同派生 classes 的对象上调用该函数,并且能够使用相同的函数而不是为每个矩阵大小使用单独的函数。
还有一个接口,任何 Base 类型的对象都将有一个矩阵 Mat,其大小将取决于创建它的 Base 的派生 class。
正如我在评论中所说,确实没有理由仅针对您所指出的内容使用 CRTP,但是如果您出于其他原因设置此模式,则类似以下的内容应该有效(我没有Eigen::Matrix
可用,所以我删除了编译器所需的接口):
#include <iostream>
namespace Eigen {
template<typename T, int W, int H>
class Matrix {
public:
static Matrix<T,W,H> Zero() {
return Matrix<T, W, H>{};
}
std::ostream &print_on(std::ostream &strm) const {
return strm;
}
};
}
template <typename T, int W, int H>
std::ostream &operator<<(std::ostream &strm, Eigen::Matrix<T,W,H> const &matrix) {
return matrix.print_on(strm);
}
template<typename T, int S>
class Base {
public:
Eigen::Matrix<int, S, S> Mat = Eigen::Matrix<int, S, S>::Zero();
virtual void print() { std::cout << Mat << std::endl; };
};
class Derived1 : public Base<Derived1,3>{
public:
};
class Derived2 : public Base<Derived2,4>{
public:
};
template <int Size>
class AdvertisingDerived : public Base<AdvertisingDerived<Size>,Size> {
public:
constexpr static int matrixSize = Size;
};
int main(){
Derived1 d1;
d1.print(); // print a 3x3 zero matrix
Derived2 d2;
d2.print(); // print a 4x4 zero matrix
AdvertisingDerived<3> ad1;
AdvertisingDerived<4> ad2;
std::cin.get();
return 0;
}
您不能访问 Derived1
的成员(从 Derived1
之外的任何地方),直到它被完全定义。此问题的通常解决方法是使用某种特征 class:
template<class D>
struct MyTraits;
template<typename T>
class Base {
public:
static const int matSize = MyTraits<T>::_matSize;
Eigen::Matrix<int, matSize, matSize> Mat = Eigen::Matrix<int, matSize, matSize>::Zero();
virtual void print() { std::cout << Mat << std::endl; };
};
class Derived1;
template<>
struct MyTraits<Derived1> {static const int _matSize = 3;};
class Derived1 : public Base<Derived1>{
public:
};
神马:https://godbolt.org/z/pf-B_R
特别是,如果 Derived1
本身是一个 class 模板,特征也将(部分)模板化。从您提供的代码很难判断这对您的情况是否有意义。
顺便说一句:应该没有必要制作 Base::print()
virtual
。静态多态的要点是避免动态多态。