使用继承或模板用于通用包装类

时间:2017-09-17 06:13:47

标签: c++ generics polymorphism

现在,我正试图在构造和操作方面抽象出C ++中矩阵和标量之间的差异。作为参考,LA lib是Eigen。

我想要这样的事情发挥作用:

template <typename T>
class Foo{
    Foo(T _val) : val(_val) { ... };
    ... // implementation
    T val;
}

operator+(Foo lhs, Foo rhs){
    ... // do something
}

所以当我这样做时:

Foo<MatrixXd> lhs(MatrixXd(2,2));

// implicitly calls Foo(10), becomes Foo<int>, 
// and does elementwise addition for example
lhs + 10; 

现在这一切都很好,但是每个人都知道模板只是鸭子打字,所以这些对象实际上是不同的,你不能把它们塞进一个通用的容器中,如:

vector<Foo> v; // obviously doesn't work; needs to have a typename specified
v.emplace_back(MatrixXd(2,2)); // and obvs these won't work either.
v.emplace_back(10);

所以我考虑过使用继承进行多态化,例如:

class Foo{
    Foo(std::unique_ptr<Base> _val) { val = std::move(_val); };
    Foo(int _val) { val = std::unique_ptr<int>(new int(_val)); };
    ... // implementation
    std::unique_ptr<Base> val;
}

operator+(Foo lhs, Foo rhs){
    auto ans = lhs.val + rhs.val; // something like this
    ...
}

但是这种方法会遇到丑陋的语法问题:

Foo lhs(new MatrixXdWrapper(3));
lhs + 2; // 2 gets implicitly copy constructed on the heap

我必须为每种类型指定一个,这是丑陋和不受欢迎的。

所以我的问题是:这些方法的问题是否有解决方法?或者我是否缺少第三种方法(可能是两者的混合),人们通常会将这些方法用于可以相互交互的通用容器类型?

谢谢!

1 个答案:

答案 0 :(得分:0)

您可以在数字中添加矩阵吗? (当然,我在数学上问你)。据我所知,操作没有定义。我认为你的问题在于你的设计,而不是你的实现。没有人会理解你的代码,因为你不能添加矩阵和数字。

如果您想“添加”矩阵和数字,您可以执行以下操作:

Matrix<10,10> A;
Matrix<10,10>::All_ones I;
int c;
auto res = A + c*I;

每个了解线性代数的人都能理解这一点,并且非常适合实施。

我不知道这是不是你想要做的。

您还可以重载运算符+:

 Matrix& operator+(Matrix& m, int c){
     // for all i, j:
     m(i,j) += c;
     return m;
 }

就是这样。我无法写出函数的正确签名,因为我不知道你的Matrix是如何定义的。也许你必须写下这样的东西:

template <size_t m, size_t n>
Matrix<m,n>& operator+(Matix<m,n>& m, int c)
{
  ...
 }

或类似的东西。

当然,请记住还要定义“c + A”,如果您希望您的运算符也可以使用不同类型的整数(无符号,长整数)或双精度运算,则可以使用类型对运算符进行参数化,或者重载operator + for int,double ...