gpt4 book ai didi

c++ - 我应该如何使用表达式模板来实现数学 vector 类的标量乘法

转载 作者:太空狗 更新时间:2023-10-29 20:55:29 25 4
gpt4 key购买 nike

请考虑数学 vector 类的以下(部分)实现(基本上是您可以在 Wikipedia article about expression templates 中找到的代码):

namespace math
{
template<class E>
class vector_expression
{
public:
std::size_t size() const {
return static_cast<E const&>(*this).size();
}

double operator[](size_t i) const
{
if (i >= size())
throw std::length_error("");
return static_cast<E const&>(*this)[i];
}

operator E&() { return static_cast<E&>(*this); }
operator E const&() const { return static_cast<E const&>(*this); }
}; // class vector_expression

template<class E1, class E2>
class vector_sum
: public vector_expression<vector_sum<E1, E2>>
{
public:
vector_sum(vector_expression<E1> const& e1, vector_expression<E2> const& e2)
: m_e1(e1), m_e2(e2)
{
if (e1.size() != e2.size())
throw std::logic_error("");
}

std::size_t size() const {
return m_e1.size(); // == m_e2.size()
}

double operator[](std::size_t i) const {
return m_e1[i] + m_e2[i];
}

private:
E1 const& m_e1;
E2 const& m_e2;
}; // class vector_sum

template<typename E1, typename E2>
vector_sum<E1, E2> operator+(vector_expression<E1> const& e1, vector_expression<E2> const& e2) {
return { e1, e2 };
}

template<typename T>
class vector
: public vector_expression<vector<T>>
{
public:
vector(std::size_t d)
: m_data(d)
{ }
vector(std::initializer_list<T> init)
: m_data(init)
{ }
template<class E>
vector(vector_expression<E> const& expression)
: m_data(expression.size())
{
for (std::size_t i = 0; i < expression.size(); ++i)
m_data[i] = expression[i];
}

std::size_t size() const {
return m_data.size();
}

double operator[](size_t i) const { return m_data[i]; }
double& operator[](size_t i) { return m_data[i]; }

private:
std::vector<T> m_data;
}; // class vector
} // namespace math

How should I extend this implementation to allow the following operations:

vector<double> x = { ... };
auto y = 4711 * x; // or y = x * 4711
auto z = 1 + x; // or x + 1, which should yield z[i] = x[i] + 1

我想我需要类似的东西

namespace math
{
template<class E, typename T>
class vector_product
: public vector_expression<vector_product<E, T>>
{
public:
vector_product(vector_expression<E> const& e, T const& t)
: m_e(e), m_t(t)
{ }

std::size_t size() const {
return m_e.size();
}

double operator[](std::size_t i) const {
return m_e[i] * m_t;
}

private:
E const& m_e;
T const& m_t;
}; // class vector_product

template<class E, typename T>
vector_product<E, T> operator*(vector_expression<E> const& e, T const& t) {
return { e, t };
}
template<class E, typename T>
vector_product<E, T> operator*(T const& t, vector_expression<E> const& e) {
return e * t;
}
} // namespace math

但我不知道这是否是一个好方法。那么,我应该怎么做呢?我应该添加任何复制或移动构造函数/赋值运算符吗?我猜不是,因为隐式变量应该做得很好,因为 vector 的唯一成员变量是 STL 类型。

最佳答案

我会简单地扩展 vector_sum允许 E2成为double ,并优雅地处理它。这将涉及采用 E1 const& 的参数和 E2 const&在你的构造函数中,可能不会抛出大小差异(因为标量没有大小),并重写 operator[]不做索引。对于最后一部分,类似于:

    double operator[](std::size_t i) const {
return m_e1[i] + get(m_e2, i);
}

private:
template <class E>
double get(E const& rhs, std::size_t i) const {
return rhs[i];
}

double get(double scalar, std::size_t ) const {
return scalar;
}

这样,如果您要添加两个 vector_expression s,你会做索引,但如果你要添加 vector_expression和一个 double - 你甚至不会尝试索引到 double .此切换发生在编译时,因此没有运行时开销。

然后,您只需要再添加几个 operator+小号:

template <typename E1>
vector_sum<E1, double> operator+(vector_expression<E1> const& e1, double d) {
return {e1, d};
}

template <typename E1>
vector_sum<E1, double> operator+(double d, vector_expression<E1> const& e1) {
return {e1, d};
}

它可以让你写:

math::vector<int> x = {1, 2, 3, 4};
math::vector<int> y = {2, 3, 4, 5};
auto sum = 3 + x + 1;

保留对 const 的引用可能不是正确的做法 - 如果您这样做了 a+b+c ,你最终会保留对临时 a+b 的引用.您可能只想保留对实际 vector 的引用,并保留所有中间对象的拷贝。


支持vector_product , 你可能需要 vector_sum<E1,E2>真的是vector_binary_op<E1,E2,std::plus<>>然后 vector_product<E1,E2>应该是 vector_binary_op<E1,E2,std::multiplies<>> .这样,您就不会拥有所有重复项。

关于c++ - 我应该如何使用表达式模板来实现数学 vector 类的标量乘法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35613620/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com