【问题标题】:Core functioning of Expression templates: assignment operator sub-template type?表达式模板的核心功能:赋值运算符子模板类型?
【发布时间】:2016-03-02 16:26:54
【问题描述】:

对不起,如果标题听起来令人困惑,但问题是。我正在研究一个非常简约的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 '='

【问题讨论】:

    标签: c++ templates


    【解决方案1】:

    因为传递给Vector&lt;T&gt;::operator= 的参数不是Expr&lt;Vector&lt;T&gt;&gt;(尤其是在使用表达式模板的情况下)。

    对于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&lt;Vector&lt;double&gt;&gt;

    编辑

    对于其他问题,

    operator= 是这里的模板函数。并且调用模板函数时不需要指定模板参数,因为Template argument deduction

    【讨论】:

    • 非常感谢!为了使答案完整,您能否详细说明为什么在赋值运算符中定义了template A,但在使用赋值运算符时从未在任何地方声明?
    • @GiovanniAzua 首先,operator= 是这里的模板函数。并且调用模板函数时不需要指定模板参数,因为Template argument deduction
    • 再次感谢您!如果您可以将这一点添加到答案中,那将是非常好的和完整的:)
    • @GiovanniAzua Fine,已添加。
    猜你喜欢
    • 2019-06-30
    • 2011-11-14
    • 2015-01-27
    • 2016-05-28
    • 2016-01-04
    • 2020-02-28
    • 2016-09-03
    相关资源
    最近更新 更多