表达式模板的核心功能:赋值运算符子模板类型



如果标题听起来令人困惑,我很抱歉,但问题是。我正在研究一个非常简约的表达式模板案例(请参阅下面的完整 C++98 代码),除了一个细节之外,我了解所有内容:为什么 Vector 类型的赋值运算符需要具有外部或第三方模板 A 才能工作?请参阅下面的注释行(抱歉找不到具有行号的方法)

#include <iostream>
using namespace std;
template <class A>
struct Expr {
    inline operator const A&() const {
        return *static_cast<const A*>(this);
    }
};
// ----------------------------------------------
// Addition Expression
// ----------------------------------------------
template<class A, class B>
class DExprSum : public Expr< DExprSum< A,B > > {
    const A& a_;
    const B& b_;
public:
    DExprSum(const A& a, const B& b) : a_(a), b_(b) { }
    double operator()(int i) const {
        return (double)(a_[i] + b_[i]);
    }
    double operator[](int i) const {
        return this->operator()(i);
    }
};
template <class A, class B>
inline DExprSum<A, B> operator+(const Expr<A>& a, const Expr<B>& b) {
    return DExprSum<A, B>(a, b);
};
// ----------------------------------------------
// A simple vector class
// ----------------------------------------------
template<class T>
class Vector : public Expr<Vector<T> > {
private:
    T *p;
    int len;
public:
    Vector(int length) {
        len = length;
        p = new T[length];
    };
    T operator()(int i) const {
        return p[i];
    }
    T& operator[](int i) const {
        return p[i];
    }
    // <<<<<<------------ HERE why do I need a new template<class A>
    // rather than simply using Expr<Vector<T> > 
    template<class A>
    void operator=(const Expr<A>& expr) {
        const A& a(expr);
        // parallelize using OpenMP
        #pragma omp parallel for schedule(runtime) // OMP_SCHEDULE=static,50 OMP_NUM_THREADS=10
        for (int i=0; i < len; ++i) {
            p[i] = a(i);
        }
    }
    ~Vector() {
        delete[] p;
    };
};
int main() {
    Vector<double> a(3);
    Vector<double> b(3);
    Vector<double> c(3);
    a[0] = 1;
    a[1] = 2;
    a[2] = 3;
    b[0] = 2;
    b[1] = 3;
    b[2] = 4;
    c = a + a + b + b;
    for (int i = 0; i < 3; ++i) {
            cout << c[i] << endl;
    }
    return 0;
}

如果我将赋值运算符定义更改为(这是实际预期):

void operator=(const Expr<Vector<T> >& expr) {
    const Vector<T>& a(expr);
    // parallelize using OpenMP
    #pragma omp parallel for schedule(runtime) // OMP_SCHEDULE=static,50 OMP_NUM_THREADS=10
    for (int i=0; i < len; ++i) {
        p[i] = a(i);
    }
}

我收到编译器错误error: no viable overloaded '='

因为传递给Vector<T>::operator=的参数不是Expr<Vector<T>>(特别是对于使用表达式模板的情况)。

对于c = a + a + b + b;,您调用operator+()三次,操作和参数将保存在表达式模板中。a + a + b + b的返回值将是

DExprSum<DExprSum<DExprSum<Vector<double>, Vector<double>>, Vector<double>>, Vector<double>>

可以投射到

Expr<DExprSum<DExprSum<DExprSum<Vector<double>, Vector<double>>, Vector<double>>, Vector<double>>>

然后将模板参数解析为 A

DExprSum<DExprSum<DExprSum<Vector<double>, Vector<double>>, Vector<double>>, Vector<double>>`

但它不能投Expr<Vector<double>>.

编辑

对于附加问题,

operator=此处是一个模板函数。并且无需指定模板参数,因为在调用模板函数时会扣除模板参数。

相关内容

最新更新