表达式模版学习笔记
请看下面这个对数组操作的表达式:
.x = 1.2*x + x*y (其中x,y都是一维数组类型的实例)
计算机世界中实现这样的操作我们基本需要两个临时变量,一个记录 array*array的中间结果,一个记录 常量*array 的中间结果。如果数组很大的情况下,这样作的效率是很低的。
改进方案一:
temp = x;
temp*=y;
x*= 1.2;
x += temp;
这个解决方案通过拆分表达式只使用了一个临时变量就达到了我们想要的结果。但带来了新的问题:
1。表达式拆分开来,给阅读带来了困难。
2。同样使用了临时变量temp,如果数组很大的情况下,同样存在效率问题。
理想的解决方案是不产生任何临时变量,同时又能够保证该表达式的书写完整性,如下:
for (int i = 0; i < 数组大小;++i)
{
x[i] = 1.2*x[i] + x[i]*y[i];
}
下面给出具体的实现代码(参见 c++ template 关于模版表达式部分)
//----------------------------------------------------------------------2

3

4
//数组类型5

6

7
template<typename T>8
class SArray 9
{10
public:11
explicit SArray (size_t s)12
: storage(new T[s]), storage_size(s) 13
{14
init();15
}16

17
SArray (SArray<T> const& orig)18
: storage(new T[orig.size()]), storage_size(orig.size())19
{20
copy(orig);21
}22
~SArray() 23
{24
delete[] storage;25
}26
SArray<T>& operator= (SArray<T> const& orig)27
{28
if (&orig!=this)29
{30
copy(orig);31
}32
return *this;33
}34
size_t size() const35
{36
return storage_size;37
}38
T operator[] (size_t idx) const39
{40
return storage[idx];41
}42
T& operator[] (size_t idx) 43
{44
return storage[idx];45
}46
protected:47
void init() 48
{49
for (size_t idx = 0; idx<size(); ++idx)50
{51
storage[idx] = T();52
}53
}54
void copy (SArray<T> const& orig)55
{56
for (size_t idx = 0; idx<size(); ++idx) 57
{58
storage[idx] = orig.storage[idx];59
}60
}61

62
private:63
T* storage;64
size_t storage_size;65
};66
//----------------------------------------------------------------------67

68

69
//表达式数组类型70

71

72

73
template <typename T, typename Rep = SArray<T> >74
class Array 75
{76
private:77
Rep expr_rep; 78
public:79
explicit Array (size_t s)80
: expr_rep(s) 81
{82
}83
Array (Rep const& rb)84
: expr_rep(rb)85
{86
}87
Array& operator= (Array const& b) 88
{ 89
for (size_t idx = 0; idx<b.size(); ++idx) 90
{91
expr_rep[idx] = b[idx];92
}93
return *this;94
}95
template<typename T2, typename Rep2>96
Array& operator= (Array<T2, Rep2> const& b)97
{ 98
for (size_t idx = 0; idx<b.size(); ++idx)99
{100
expr_rep[idx] = b[idx];101
}102
return *this;103
}104
size_t size() const 105
{106
return expr_rep.size();107
}108
T operator[] (size_t idx) const109
{110
return expr_rep[idx];111
}112
T& operator[] (size_t idx)113
{114
return expr_rep[idx];115
}116
Rep const& rep() const 117
{118
return expr_rep;119
}120
Rep& rep()121
{122
return expr_rep;123
}124
};125

126
//----------------------------------------------------------------------127

128

129
//数值类型封装130

131

132
template <typename T>133
class A_Scalar134
{135
private:136
T const& s;137
public:138
A_Scalar (T const& v)139
: s(v) 140
{141
}142
T operator[] (size_t) const143
{144
return s;145
}146
size_t size() const 147
{148
return 0;149
};150
};151

152
//----------------------------------------------------------------------153

154

155
//类型封装定义156

157
template <typename T>158
class A_Traits 159
{160
public:161
typedef T const& ExprRef;162
};163

164
template <typename T>165
class A_Traits<A_Scalar<T> >166
{167
public:168
typedef A_Scalar<T> ExprRef;169
};170

171
//----------------------------------------------------------------------172

173

174
//表达式封装175

176

177
template <typename T, typename OP1, typename OP2>178
class A_Add179
{180
private:181
typename A_Traits<OP1>::ExprRef op1;182
typename A_Traits<OP2>::ExprRef op2;183

184
public: 185
A_Add (OP1 const& a, OP2 const& b)186
: op1(a), op2(b) 187
{188
}189
T operator[] (size_t idx) const190
{191
return op1[idx] + op2[idx];192
}193
size_t size() const 194
{195
return op1.size()!=0 ? op1.size() : op2.size();196
}197
};198

199
template <typename T, typename OP1, typename OP2>200
class A_Mult201
{202
private:203
typename A_Traits<OP1>::ExprRef op1;204
typename A_Traits<OP2>::ExprRef op2;205

206
public:207
A_Mult (OP1 const& a, OP2 const& b)208
: op1(a), op2(b)209
{210
}211
T operator[] (size_t idx) const212
{213
return op1[idx] * op2[idx];214
}215
size_t size() const216
{217
return op1.size()!=0 ? op1.size() : op2.size();218
}219
};220

221
//----------------------------------------------------------------------222

223
//操作封装224

225

226
template <typename T, typename R1, typename R2> Array<T,A_Add<T,R1,R2> > operator+ (Array<T,R1> const& a, Array<T,R2> const& b)227
{228
return Array<T,A_Add<T,R1,R2> >(A_Add<T,R1,R2>(a.rep(),b.rep()));229
}230
template <typename T, typename R1, typename R2>231
Array<T, A_Mult<T,R1,R2> > operator* (Array<T,R1> const& a, Array<T,R2> const& b)232
{233
return Array<T,A_Mult<T,R1,R2> >(A_Mult<T,R1,R2>(a.rep(), b.rep()));234
}235
template <typename T, typename R2> Array<T, A_Mult<T,A_Scalar<T>,R2> > operator* (T const& s, Array<T,R2> const& b)236
{237
return Array<T,A_Mult<T,A_Scalar<T>,R2> >(A_Mult<T,A_Scalar<T>,R2>(A_Scalar<T>(s), b.rep()));238
}239
//----------------------------------------------------------------------240

241

测试代码如下:

2
//----------------------------------------------------------------------3
//定义,初始化4

5
Array<double> x(1000), y(1000);6
for (int i=0; i<1000; ++i)7
{8
x[i] = i;9
y[i] = x[i]+x[i];10
}11

12
//----------------------------------------------------------------------13

14
//使用测试15

16
std::cout << "x: ";17
print(x);18

19
std::cout << "y: ";20
print(y);21

22
x = 1.2 * x;23
std::cout << "x = 1.2 * x: ";24
print(x);25

26
x = 1.2*x + x*y;27
std::cout << "1.2*x + x*y: ";28
print(x);29

30
x = y;31
std::cout << "after x = y: ";32
print(x);33

34
//----------------------------------------------------------------------35

该解决方案分析:
1。表达式的计算延迟到赋值得时候才进行。
2。通过对象编译时封装了表达式信息。
3。利用 trait 技术提供类型封装。
4。效率高,没有任何临时变量的产生。


浙公网安备 33010602011771号