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

时间:2016-03-02 07:51:49

标签: c++ templates

对不起,如果标题听起来令人困惑,但问题是。我正在研究一个极简主义的Expression Templates案例(参见下面的完整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 '='

1 个答案:

答案 0 :(得分:2)

因为传递给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=是一个模板函数。在调用模板函数时,无需指定模板参数,因为Template argument deduction