特定构造函数的预设模板参数

时间:2014-08-09 17:16:07

标签: c++ templates constructor type-conversion linear-algebra

我目前正在使用C ++实现科学工具包。当我实现Matrix类时,我遇到了转换构造函数的问题:

template<size_t ROWS, size_t COLS = ROWS>
class Matrix {
public:

    ...

    /** \brief Creates a matrix from a vector */
    Matrix<ROWS, 1> (const Vector<ROWS>& vector) {
        for (size_t i = 0; i < ROWS; i++) {
        (*this)[i][0] = vector[i];
    }

    ...

}

这段代码使用clang ++编译得很好,但是无法使用g ++和

matrix.h:43:18: error: invalid declarator before ‘(’ token
  Matrix<ROWS, 1> (const Vector<ROWS>& vector) {

是否有其他方法可以强制特定构造函数的某些模板参数?我这样做的方式不符合标准,还是应该向gcc报告错误?

2 个答案:

答案 0 :(得分:1)

使用像这样的部分专业化:

template<size_t ROWS, size_t COLS = ROWS>
class Matrix {
    // ... (regular ROWS x COLS matrix code)
};

template<size_t ROWS>
class Matrix<ROWS, 1u> {
// ... (more ROWS x 1 matrix code)
    /// \brief Creates a matrix from a vector
    Matrix(const Vector<ROWS> & vector) {
        for (size_t i = 0u; i < ROWS; i++)
            (*this)[i][0u] = vector[i];
    }
// ... (more ROWS x 1 matrix code)

};

或者,如果这会导致代码重复太多,只需为专门化声明一个公共基类。例如像这样(在中):

template<size_t ROWS, size_t COLS = ROWS>
class MatrixBase {
    // ... (regular ROWS x COLS matrix code)
};

template<size_t ROWS, size_t COLS = ROWS>
class Matrix: public MatrixBase<ROWS, COLS> {
public: /* Methods: */
    using MatrixBase<ROWS, COLS>::MatrixBase;
};

template<size_t ROWS>
class Matrix<ROWS, 1u>: public MatrixBase<ROWS, 1u> {
public: /* Methods: */
    using MatrixBase<ROWS, 1u>::MatrixBase;
    Matrix(const Vector<ROWS> & vector) {
        for (size_t i = 0u; i < ROWS; i++)
            (*this)[i][0u] = vector[i];
    }
};

对于C ++ 03及更早版本,您不能以这种方式使用using关键字,并且可能仍需要为调用相应基类构造函数的所有特化项定义构造函数,例如: Matrix(SomeArg arg) : MatrixBase(arg) {}。如果你正在使用GCC 4.7,不支持这个C ++ 11 using语句,你可以使用完美转发来避免在所有基类构造函数的特化中编写单独的构造函数,例如: template <typename ... Args> Matrix(Args && ... args) : MatrixBase(std::forward<Args>(args)...) {}

答案 1 :(得分:1)

  

是否有必要重新实现所有方法,或者在某种程度上可以在专用模板中使用非专用方法而不重复代码?

部分专用类不包含主模板的成员函数,静态成员函数,枚举,成员类等的声明。因此,如果要使用它们,则必须重新定义整个类并重新实现它们。作为替代方案,如果您支持C ++ 11,则可以通过基于给定条件调用私有构造函数来使用构造函数委派:

template<size_t ROWS, size_t COLS = ROWS>
class Matrix
{
public:
    Matrix(const Vector<ROWS>& vector)
        : Matrix(vector, std::integral_constant<bool, COLS == 1>())
    { }
private:
    // Implementation for COLS == 1
    Matrix(const Vector<ROWS>& vector, std::true_type)
    {
    }

    // Implementation for COLS != 1
    Matrix(const Vector<ROWS>& vector, std::false_type)
    {
    }
};