2016-03-02 74 views
2

如果标题听起来很混乱,但问题是,我很抱歉。我正在研究极简主义案例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 '='

回答

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=是这里的模板功能。在调用模板函数时,不需要指定模板参数,因为。

+0

非常感谢!为了让答案完整,请您详细说明为什么'template A'是在赋值运算符中定义的,但是在使用赋值运算符时从未在任何地方声明过? –

+1

@GiovanniAzua首先,'operator ='是一个模板函数。在调用模板函数时,由于[Template argument deduction](http://en.cppreference.com/w/cpp/language/template_argument_deduction),不需要指定模板参数。 – songyuanyao

+0

再次感谢您!如果你可以添加这一点的答案将是非常好的和完整:) –