首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >C++11模板,确定返回类型

C++11模板,确定返回类型
EN

Stack Overflow用户
提问于 2011-05-27 05:21:54
回答 5查看 626关注 0票数 14

我正在构建一个矩阵库,并尝试使用policy-based design。所以我的基类是提供存储方法和一些访问函数的类。我还有一个函数矩阵,它提供了数学函数。这很有效,但由于返回类型的原因,运算符*存在一个主要问题。我将用一些代码来解释它。

提供堆栈存储的基类:

代码语言:javascript
运行
复制
template < typename T, unsigned int rows, unsigned int cols>
class denseStackMatrix {
public:
    typedef T value_type;

private:
    value_type grid[rows][cols];
    const unsigned int rowSize;
    const unsigned int colSize;

然后我有我的矩阵类,它提供了数学功能:

代码语言:javascript
运行
复制
template <typename MatrixContainer >
class matrix : public MatrixContainer {
public:
    typedef MatrixContainer Mcontainer;

    matrix<Mcontainer>& operator +(const matrix<Mcontainer>&);
    matrix<Mcontainer>& operator *(const matrix<Mcontainer>&);

operator+总是有效的,operator*只适用于方阵。所以我们仍然需要一个来处理所有的矩阵。这就是它出错的地方。我已经尝试了几种方法,但都不起作用。我寻找这样的东西,在c++0x的帮助下(使用c++0x不是必需的),你会注意到“?”:)

代码语言:javascript
运行
复制
friend auto operator * (const matrix<T1>& matrix1, const matrix<T2>& matrix2)
-> decltype(matrix<???>);

这个问题的一个例子

代码语言:javascript
运行
复制
matrix<denseStackMatrix<int,3,2> > matrix1;
matrix<denseStackMatrix<int,2,4> > matrix2;
matrix<denseStackMatrix<int,3,4> > matrix3 = matrix1 * matrix2;

在这里,它将抱怨类型,因为它不匹配两个参数类型中的任何一个。但是编译器需要知道编译时的类型,而我不知道如何提供它。

我知道设计还有其他选择,但我真的在为这个场景寻找解决方案。

谢谢!

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2011-05-27 07:02:58

采用@hammar的想法,但使用部分专门化,以允许正常语法,如问题所示:

代码语言:javascript
运行
复制
template<class MatrixContainer>
class matrix;

template<
  template<class,int,int> class MatrixContainer,
  class T, int rows, int cols
>
class matrix< MatrixContainer<T,rows,cols> >{
  typedef MatrixContainer<T,rows,cols> Mcontainer;
  typedef matrix<Mcontainer> this_type;
  static int const MyRows = rows;
  static int const MyCols = cols;

public:
  template<int OtherCols>
  matrix<MatrixContainer<T,MyRows,OtherColls> > operator*(matrix<MatrixContainer<T,MyCols,OtherCols> > const& other){
    typedef matrix<MatrixContainer<T,MyCols,OtherCols> > other_type;
    typedef matrix<MatrixContainer<T,MyRows,OtherCols> > result_type;
    // ...
  }
};

编辑:正如您在评论中所说,您还可以使用它来创建一个不使用以行和列大小作为模板参数的MatrixContainer的矩阵:

代码语言:javascript
运行
复制
template<
  template<class> class MatrixContainer,
  class T
>
class matrix< MatrixContainer<T> >{
  typedef MatrixContainer<T> Mcontainer;
  typedef matrix<Mcontainer> this_type;

public:
  // normal matrix multiplication, return type is not a problem
  this_type operator*(this_type const& other){
    // ensure correct row and column sizes, e.g. with assert
  }

  // multiply dynamic matrix with stack-based one:
  template<
    template<class,int,int> class OtherContainer,
    int Rows, int Cols
  >
  this_type operator*(matrix<OtherContainer<T,Rows,Cols> > const& other){
    // ensure correct row and column sizes, e.g. with assert
  }
};

用法:

代码语言:javascript
运行
复制
// stack-based example
matrix<DenseStackMatrix<int,3,2> > m1;
matrix<DenseStackMatrix<int,2,4> > m2;
matrix<DenseStackMatrix<int,3,4> > m3 = m1 * m2;

// heap-based example
matrix<DenseHeapMatrix<int> > m1(3,2);
matrix<DenseHeapMatrix<int> > m2(2,4);
matrix<DenseHeapMatrix<int> > m3 = m1 * m2;
票数 5
EN

Stack Overflow用户

发布于 2011-05-27 06:52:02

如何将MatrixContainer更改为模板模板参数?

代码语言:javascript
运行
复制
template <class T, int Rows, int Cols>
class DenseStackMatrix {
public:
    typedef T value_type;

private:
    value_type grid[Rows][Cols];
};

template <class T, int Rows, int Cols, template<class, int, int> class MatrixContainer>
class Matrix : public MatrixContainer<T, Rows, Cols> {
public:
    template <int ResultCols>
    Matrix<T, Rows, ResultCols, MatrixContainer> & operator*(const Matrix<T, Cols, ResultCols, MatrixContainer> &);
};

int main() {
    Matrix<int, 3, 2, DenseStackMatrix> matrix1;
    Matrix<int, 2, 4, DenseStackMatrix> matrix2;
    Matrix<int, 3, 4, DenseStackMatrix> matrix3 = matrix1 * matrix2;
}

这样,您不仅可以进行编译时维度检查,还可以对其进行扩展,以允许不同容器类型的矩阵之间的乘法。

票数 3
EN

Stack Overflow用户

发布于 2011-05-27 08:52:27

只是因为我在这里找到所有的答案之前就做过了:

代码语言:javascript
运行
复制
template <typename T, unsigned int M, unsigned int N>
struct Matrix
{
};

template <typename T, unsigned int M, unsigned int MN, unsigned int N>
Matrix<T, M, N> operator*(Matrix<T, M, MN> const & lhs, Matrix<T, MN, N> const & rhs)
{
    return Matrix<T, M, N>();
}

int main()
{
    Matrix<int, 3, 4> prod = Matrix<int, 3, 2>() * Matrix<int, 2, 4>();

    // Fails to compile as desired
    // g++ gives:
    //matrix.cpp: In function 'int main()':
    //matrix.cpp:20: error: no match for 'operator*' in 'Matrix<int, 3u, 2u>() * Matrix<int, 3u, 4u>()'
    Matrix<int, 3, 4> prod1 = Matrix<int, 3, 2>() * Matrix<int, 3, 4>();
}

此解决方案可能不适合您的设计模式,但使用operator*的自由函数实现来推断(和检查)模板参数,如果不满足矩阵乘法的约束,则会导致编译时错误。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6145247

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档