【问题标题】:Preset template argument for specific constructor特定构造函数的预设模板参数
【发布时间】:2014-08-09 17:16:06
【问题描述】:

我目前正在使用 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 报告错误?

【问题讨论】:

  • 不知道为什么 clang 会接受这个,因为 Maxtrix&lt;ROWS, 1&gt; 可能是一个与主模板实例化的模板参数完全不同的类。您可以创建一个部分专用的类并根据需要实现构造函数。

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


【解决方案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) {}。如果您使用的是不支持此 C++11 using 语句的 GCC 4.7,则可以使用完美转发来避免在所有基类构造函数的特化中编写单独的构造函数,例如template &lt;typename ... Args&gt; Matrix(Args &amp;&amp; ... args) : MatrixBase(std::forward&lt;Args&gt;(args)...) {}.

【讨论】:

  • 是否有必要重新实现所有方法,或者是否可以在不重复代码的情况下在专用模板中使用非专用方法?
  • @richard 您可以实现一个通用基类,您可以从该基类公开派生您的专业。
【解决方案2】:

是否有必要重新实现所有方法,或者是否可以在不重复代码的情况下在专用模板中使用非专用方法?

部分特化的类不包含主模板的成员函数、静态成员函数、枚举、成员类等的声明。因此,如果要使用它们,则必须重新定义整个类并重新实现它们。作为替代方案,如果您支持 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)
    {
    }
};

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-15
    • 2011-05-08
    • 2023-02-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多