【发布时间】:2016-01-07 05:25:56
【问题描述】:
这个问题专门针对一些帮助类Traits 的实现,用于自动生成某种二阶函数。
例如有两个不同的对象
//some realization of matrix
class MatrixA{
...
};
//totally different realization with different
//public members, different constructors etc.
class MatrixB{
...
};
我想在一些高度抽象的代码中使用这两个功能相同的对象(例如在矩阵对角化中)。抽象在这里意味着我们不需要对矩阵对象的特定实现一无所知。取而代之的是,我们应该只定义一些标准运算,例如矩阵求和、向量乘法等。
为了做到这一点,我使用了一些特征接口
//traits
//template interface for matrix algebra
template<typename MatrixType>
class TemplateAlgebra{
typedef MatrixType matrix_t;
public:
virtual matrix_t matrix_add(const matrix_t& m1,
const matrix_t& m2) const=0;
};
//template traits class
template<typename MatrixType, typename MatrixAlgebra>
class TemplateTraits{
public:
typedef MatrixType matrix_t;
typedef MatrixAlgebra matrix_algebra_t;
};
我在这里定义了一些模板操作(例如这里的求和)。
然后通过为每个矩阵类型定义一个特定的实现
//overriding of concrete matrix algebra for MatrixA type
class AlgebraA:
public TemplateAlgebra<MatrixA>{
public:
MatrixA matrix_add(const MatrixA& m1,
const MatrixA& m2) const override{
//here we use some operations from MatrixA class
}
};
//and create a traits for MatrixA
typedef TemplateTraits<MatrixA,AlgebraA> ATraits;
我在一些通用接口中抽象出每种矩阵类型的单独属性。
所有这些都可以正常工作。
当我试图从一般的知识中生成一些额外的功能时,问题就开始了。
//here the place with errors
//the goal of this class is to generate some second-order functions
//from knowledge of some basic functions which defined in traits
template<typename Traits>
class AutoGenerator:
public Traits::matrix_algebra_t{
typedef typename Traits::matrix_t matrix_t;
typedef typename Traits::matrix_algebra_t matrix_algebra_t;
public:
AutoGenerator(){}
//some member function works perfectly
void sum(const matrix_t& m1, const matrix_t& m2){
matrix_algebra_t::matrix_add(m1,m2);//works fine
}
//however there is a problem with friend declaration!
template<typename T=Traits>
friend matrix_t operator+(const matrix_t& m1, const matrix_t& m2){
matrix_algebra_t::matrix_add(m1,m2);//doen't work
}
};
特别是您可以看到某些运算符的生成存在问题。编译时出现错误:error: cannot call member function "...::matrix_add" without object.
我很清楚为什么会发生这个错误,所以请不要向我解释我试图在没有类对象的情况下调用非静态成员。我只是在这个可能很简单的问题上陷入僵局,因为我花了很多时间处理它,但我没有看到解决方案。
所以,最后,问题是“如何通过使用某些模板特征类来重载运算符?”。特别是+ 运算符。
很抱歉,这是一个很长的解释,我只是想避免一些“愚蠢”的答案,比如“只需将它添加到特定的矩阵类中”。我不想修改特定的类(通过使用矩阵的外部库,我什至无法访问它)。并提前感谢您的帮助!
【问题讨论】:
-
你为什么还要使用虚函数?既然整个事情看起来都是基于模板的,为什么不完全摆脱对象并在
TemplateAlgebra中使用静态成员函数呢?AlberaA将是TemplateAlgebra的专业化,而不是从它派生的类。 -
可能我错了,但是通过以这种方式使用静态函数,整个代码中的重载运算符将是相同的。我没有在解释中提到我想在代码的不同部分使用不同的生成器类。这是必要的,因为我使用了一些外部库,这些库需要重载运算符的不同结果(例如在 boost::odeint 中一个结果,在对角化的库中另一个)。这就是为什么静态函数的实现不适合我的情况的原因。
标签: c++ templates c++11 operator-overloading traits