模板与构造函数参数在数值参数集方面的区别

4

我对C++模板还比较陌生,正在实现一些数值计算程序。特别是,我正在查看一些代码,其风格是如果要定义一个向量,它将如下所示:

template <class Field>
class Vector2
{
    private:
    std::vector<Field> container;

    public:
    Vector2(size_t size) : container(std::vector<Field>(size, Field(0))) {}
    Vector2(const Vector2<Field> &source) : container(source.container) {}

          Field & operator[](size_t index) { return container.at(index); }
    const Field & operator[](size_t index) const { return container.at(index); }

    Vector2<Field> operator+( const Vector2<Field> & rhs) const {
        if (rhs.container.size() != container.size())
            throw new std::invalid_argument("wrong size");

        Vector2<Field> sum(*this);
        for (int i = 0; i < container.size(); i++)
            sum[i] += rhs[i];
        return sum;
    }
};

然而,如果我在设计类模板时,我会选择在模板参数中指定大小:

template <int size, class Field>
class Vector1
{
    private:
    std::vector<Field> container;

    public:
    Vector1() : container(std::vector<Field>(size, Field(0))) {}
    Vector1(const Vector1<size, Field> &source) : container(source.container) {}

    Field & operator[](size_t index) { return container.at(index); }
    const Field & operator[](size_t index) const { return container.at(index); }

    Vector1<size, Field> operator+( const Vector1<size, Field> & rhs) const {
        Vector1<size, Field> sum;
        for (int i = 0; i < size; i++)
            sum[i] += rhs[i];
        return sum;
    }
};

我认为这样做可以防止像是将两个不同维度的向量相加这样的事情发生,因为它们会成为不同的类。特别地,像下面这样的情况:

Vector1<double> a (3);
Vector1<double> b (4);
Vector1<double> c = a + b;

需要运行时检查大小,

Vector2<3,double> a;
Vector2<4,double> b;
Vector2<5,double> c = a + b;

这段代码甚至无法编译。由于此代码是数值分析包的一部分,执行速度至关重要,我必须假设作者已经考虑过这些问题。在代码中,这种风格用于向量、矩阵和其他被解释为数值参数集合元素(即不同维度的向量空间)的对象。

因此,我的问题是:

有没有执行速度方面的考虑,会暗示构造函数参数方法比模板参数方法更好?


这个类有什么意义? - Seth Carnegie
@Seth; 关键是要拥有用于数值线性代数的对象。 - JRG
我刚刚重新阅读了问题,看到了“仿佛”的字眼。之前,我在想Vector2类的意义何在,但现在我明白这只是一个例子。 - Seth Carnegie
2个回答

3
当向量大小是运行时参数时,二元运算必须在运行时检查操作数的大小是否一致。
理想情况下,C++ 数值计算包应该提供模板,其中包括运行时指定大小和编译时指定大小,并且它们应该是可互换的。在编译时指定大小只能提高性能。
你可以通过使用 std::array/boost::array 替换给定实现中的 std::vector 来实现你的建议。如果模板参数仅用于定义运行时参数,则不会获得任何好处。

2

即可变维度的向量空间

如果维度在编译时不知道,那么它不能成为模板参数。无法更改。

模板在编译时更加强大,但以运行时的某些灵活性为代价。


在这个例子中,不使用模板也不会更灵活,因为你只是将大小检查移动到运行时,这当然会稍微慢一些。 - Seth Carnegie

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接