gpt4 book ai didi

c++ - 表达式模板 - C++ 模板 : The Complete Guide

转载 作者:行者123 更新时间:2023-11-28 05:30:04 36 4
gpt4 key购买 nike

我正在研究c++模板,正在阅读< >。我不明白 flowing about 表达式模板:

代码如下:

//exprarray.h
#include <stddef.h>
#include <cassert>
#include "sarray.h"

template<typename T>
class A_Scale
{
public:
A_Scale(T const& t):value(t){}
T operator[](size_t) const
{
return value;
}
size_t size() const
{
return 0;
}
private:
T const& value;
};

template<typename T>
class A_Traits
{
public:
typedef T const& exprRef;
};
template<typename T>
class A_Traits<A_Scale<T> >
{
public:
typedef A_Scale<T> exprRef;
};

template<typename T,typename L1,typename R2>
class A_Add
{
private:
typename A_Traits<L1>::exprRef op1;
typename A_Traits<R2>::exprRef op2;
public:
A_Add(L1 const& a,R2 const& b):op1(a),op2(b)
{
}
T operator[](size_t indx) const
{
return op1[indx] + op2[indx];
}
size_t size() const
{
assert(op1.size()==0 || op2.size()==0 || op1.size() == op2.size());
return op1.size() != 0 ? op1.size() : op2.size();
}
};

template<typename T,typename L1,typename R2>
class A_Mul
{
private:
typename A_Traits<L1>::exprRef op1;
typename A_Traits<R2>::exprRef op2;
public:
A_Mul(L1 const& a,R2 const& b):op1(a),op2(b)
{
}
T operator[](size_t indx) const
{
return op1[indx] * op2[indx];
}
size_t size() const
{
assert(op1.size()==0 || op2.size()==0 || op1.size() == op2.size());
return op1.size() != 0 ? op1.size():op2.size();
}
};

template<typename T,typename Rep = SArray<T> >
class Array
{
public:
explicit Array(size_t N):expr_Rep(N){}
Array(Rep const& rep):expr_Rep(rep){}
Array& operator=(Array<T> const& orig)
{
assert(size() == orig.size());
for (size_t indx=0;indx < orig.size();indx++)
{
expr_Rep[indx] = orig[indx];
}
return *this;
}
template<typename T2,typename Rep2>
Array& operator=(Array<T2,Rep2> const& orig)
{
assert(size() == orig.size());
for (size_t indx=0;indx<orig.size();indx++)
{
expr_Rep[indx] = orig[indx];
}
return *this;
}
size_t size() const
{
return expr_Rep.size();
}
T operator[](size_t indx) const
{
assert(indx < size());
return expr_Rep[indx];
}
T& operator[](size_t indx)
{
assert(indx < size());
return expr_Rep[indx];
}
Rep const& rep() const
{
return expr_Rep;
}
Rep& rep()
{
return expr_Rep;
}
private:
Rep expr_Rep;
};

template<typename T,typename L1,typename R2>
Array<T,A_Add<T,L1,R2> >
operator+(Array<T,L1> const& a,Array<T,R2> const& b)
{
return Array<T,A_Add<T,L1,R2> >(A_Add<T,L1,R2>(a.rep(),b.rep()));
}

template<typename T,typename L1,typename R2>
Array<T,A_Mul<T,L1,R2> >
operator*(Array<T,L1> const& a,Array<T,R2> const& b)
{
return Array<T,A_Mul<T,L1,R2> >(A_Mul<T,L1,R2>(a.rep(),b.rep()));
}

template<typename T,typename R2>
Array<T,A_Mul<T,A_Scale<T>,R2> >
operator*(T const& a,Array<T,R2> const& b)
{
return Array<T,A_Mul<T,A_Scale<T>,R2> >(A_Mul<T,A_Scale<T>,R2>(A_Scale<T>(a),b.rep()));
}

测试代码:

//test.cpp
#include "exprarray.h"
#include <iostream>
using namespace std;

template <typename T>
void print (T const& c)
{
for (int i=0; i<8; ++i) {
std::cout << c[i] << ' ';
}
std::cout << "..." << std::endl;
}

int main()
{
Array<double> x(1000), y(1000);

for (int i=0; i<1000; ++i) {
x[i] = i;
y[i] = x[i]+x[i];
}

std::cout << "x: ";
print(x);

std::cout << "y: ";
print(y);

x = 1.2 * x;
std::cout << "x = 1.2 * x: ";
print(x);

x = 1.2*x + x*y;
std::cout << "1.2*x + x*y: ";
print(x);

x = y;
std::cout << "after x = y: ";
print(x);

return 0;
}

我的问题是为什么 A_Scale 的 A_Traits 是按值而不是按引用。

template<typename T>
class A_Traits
{
public:
typedef T const& exprRef;
};
template<typename T>
class A_Traits<A_Scale<T> >
{
public:
typedef A_Scale<T> exprRef;
};

书上的原因如下:

This is necessary because of the following: In general, we can declare them to be references because most temporary nodes are bound in the top-level expression and therefore live until the end of the evaluation of that complete expression. The one exception are the A_Scalar nodes. They are bound within the operator functions and might not live until the end of the evaluation of the complete expression. Thus, to avoid that the members refer to scalars that don't exist anymore, for scalars the operands have to get copied "by value."

更多细节请引用第18章C++ Templates: The Complete Guide

最佳答案

例如,考虑右侧

x = 1.2*x + x*y;

引用的内容是,它由两个不同的类别组成。

array xy 对象不是在这个表达式中定义的,而是在它之前定义的:

Array<double> x(1000), y(1000);

因此,当您使用它们构建表达式时,您不必担心它们是否仍然存在 - 它们是预先定义的。由于它们很重,您希望通过引用来捕获它们,幸运的是,它们的生命周期使这成为可能。

相反,轻量级 A_Scale 对象是表达式中生成的(例如,由上面的 1.2 隐式生成)。由于它们是临时的,因此您必须担心它们的生命周期。因为它们很轻,所以这不是问题。

这就是 traits 类区分它们的基本原理:前者通过引用,后者通过值(它们被复制)。

关于c++ - 表达式模板 - C++ 模板 : The Complete Guide,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39759531/

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