使用CRTP重载std :: swap()

时间:2014-08-04 17:25:08

标签: c++ c++11 swap crtp

好的我有两个类matrix_rowmatrix_column,它们(正如他们的名字所说)代表矩阵的行和列。我这样做是为了以简单的方式在矩阵行/列("行")之间进行操作。类似于m1.row(1) = m1.column(0) + m2.row(7)

由于两种类型的行几乎是相同的,除了访问底层元素的方式之外,我有一个包含所有操作的CRTP基类。然后上面提到的两个类继承它并指定自己通过静态分派访问元素的方式:

template<typename T , std::size_t ROWS , std::size_t COLUMNS , typename DERIVED>
struct line
{
    std::reference_wrapper<matrix<T,ROWS,COLUMNS>> ref;
    std::size_t index;

    ...
};

template<typename T , std::size_t ROWS , std::size_t COLUMNS>
struct matrix_row : public line<T,ROWS,COLUMNS,matrix_row<T,ROWS,COLUMNS>>
{
    const T& at( std::size_t index ) const { return this->matrix_ref.get()[this->index][index]; }
          T& at( std::size_t index )       { return this->matrix_ref.get()[this->index][index]; }  

    using base_t::operator=;
};

template<typename T , std::size_t ROWS , std::size_t COLUMNS>
struct matrix_column : public line<T,ROWS,COLUMNS,matrix_column<T,ROWS,COLUMNS>>
{
    const T& at( std::size_t index ) const { return this->matrix_ref.get()[index][this->index]; }
          T& at( std::size_t index )       { return this->matrix_ref.get()[index][this->index]; }  

    using base_t::operator=;
};

在此之前似乎一切都有效,包括不同类型的线之间的分配。现在我想为线路重载std::swap(),对于需要矩阵线交换的算法(例如像高斯消除一样)。所以我在自己的命名空间中添加了swap()函数:

template<typename LHS_T , typename RHS_T , 
         std::size_t LHS_Rs , std::size_t RHS_Rs ,
         std::size_t LHS_Cs , std::size_t RHS_Cs ,
         typename LHS_D , typename RHS_D
        >         
friend void swap( line<LHS_T,LHS_Rs,LHS_Cs,LHS_D>& lhs , line<RHS_T,RHS_Rs,RHS_Cs,RHS_D>& rhs )
{
    assert( lhs.length == rhs.length );

    for( std::size_t i = 0 ; i < lhs.length ; ++i )
        std::swap( lhs[i] , rhs[i] );
}

由于我需要可交换的不同线型(例如,交换一个矩阵的一列具有相同长度的一行),我将该函数定义为使用基本而不是派生类型。

我有两个问题:

  • 所有机制都在基类上,派生类仅用于提供自定义访问(at())方法。 即使派生类的内存布局是(因为没有virtual也没有额外的数据成员),因此我会以这种方式进行交换切片问题,这就像基地的布局?

  • 使用该swap()模板时,编译器会报告no known conversion from [derived] to [base]&错误。 我错过了什么?如果我使用对基类的引用,为什么需要进行转换?

0 个答案:

没有答案