【问题标题】:Operators overloading in generated class based on the methods of base class基于基类方法的生成类中的运算符重载
【发布时间】: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


【解决方案1】:

这就是区别。您的void sum(const matrix_t&amp; m1, const matrix_t&amp; m2)AutoGenerator 的成员,它派生自matrix_algebra_t,因此调用matrix_algebra_t::matrix_add(...) 有效地调用了基类中的函数。

但是,您的template<typename T=Traits> friend matrix_t operator+(const matrix_t& m1, const matrix_t& m2) 不是AutoGenerator 的成员,因此要能够在其中调用matrix_algebra_t::matrix_add(...)matrix_add() 应该是matrix_algebra_t 的静态函数。您需要创建一个matrix_algebra_t 的对象,并在其上调用函数:

matrix_algebra_t().matrix_add(m1,m2);

【讨论】:

  • 非常感谢!现在它起作用了!在每次调用运算符期间创建对象将如何影响性能?还是编译器应该优化它?
  • @QuantumNik,很难说。如果你关心的话,如果可以使 matrix_algebra 实例 static (假设在同一个实例上多次调用 matrix_add 不会弄乱它的状态)。
【解决方案2】:

您的代数课似乎没有数据。在这种情况下,创建它的按需实例应该很简单:

template<typename T=Traits>
friend matrix_t operator+(const matrix_t& m1, const matrix_t& m2){
  matrix_algebra_t().matrix_add(m1,m2);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-04
    • 2018-12-01
    相关资源
    最近更新 更多