表达式模版学习笔记

   请看下面这个对数组操作的表达式:
                     
                                 .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 关于模版表达式部分)


  1//----------------------------------------------------------------------
  2
  3
  4//数组类型
  5
  6
  7template<typename T>
  8class SArray 
  9{
 10public:
 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() const
 35    {
 36        return storage_size;
 37    }

 38    T operator[] (size_t idx) const
 39    {
 40        return storage[idx];
 41    }

 42    T& operator[] (size_t idx) 
 43    {
 44        return storage[idx];
 45    }

 46protected:
 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
 62private:
 63    T*     storage;
 64    size_t storage_size;
 65}
;
 66//----------------------------------------------------------------------
 67
 68
 69//表达式数组类型
 70
 71
 72
 73template <typename T, typename Rep = SArray<T> >
 74class Array 
 75{
 76private:
 77    Rep expr_rep; 
 78public:
 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) const
109    {
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
132template <typename T>
133class A_Scalar
134{
135private:
136    T const& s;
137public:
138    A_Scalar (T const& v)
139        : s(v) 
140    {
141    }

142    T operator[] (size_t) const
143    {
144        return s;
145    }

146    size_t size() const 
147    {
148        return 0;
149    }
;
150}
;
151
152//----------------------------------------------------------------------
153
154
155//类型封装定义
156
157template <typename T>
158class A_Traits 
159{
160public:
161    typedef T const& ExprRef;
162}
;
163
164template <typename T>
165class A_Traits<A_Scalar<T> >
166{
167public:
168    typedef A_Scalar<T> ExprRef;
169}
;
170
171//----------------------------------------------------------------------
172
173
174//表达式封装
175
176
177template <typename T, typename OP1, typename OP2>
178class A_Add
179{
180private:
181    typename A_Traits<OP1>::ExprRef op1;
182    typename A_Traits<OP2>::ExprRef op2;
183
184public
185    A_Add (OP1 const& a, OP2 const& b)
186        : op1(a), op2(b) 
187    {
188    }

189    T operator[] (size_t idx) const
190    {
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
199template <typename T, typename OP1, typename OP2>
200class A_Mult
201{
202private:
203    typename A_Traits<OP1>::ExprRef op1;
204    typename A_Traits<OP2>::ExprRef op2;
205
206public:
207    A_Mult (OP1 const& a, OP2 const& b)
208        : op1(a), op2(b)
209    {
210    }

211    T operator[] (size_t idx) const
212    {
213        return op1[idx] * op2[idx];
214    }

215    size_t size() const
216    {
217        return op1.size()!=0 ? op1.size() : op2.size();
218    }

219}
;
220
221//----------------------------------------------------------------------
222
223//操作封装
224
225
226template <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}

230template <typename T, typename R1, typename R2>
231Array<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}

235template <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


测试代码如下:
         

 1
 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*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。效率高,没有任何临时变量的产生。





posted on 2007-02-03 01:02  小峰  阅读(386)  评论(2)    收藏  举报

导航