C + + implements Vector's arithmetic _c language

Source: Internet
Author: User
Tags arithmetic

This assumes that the operation of the vector is defined as an operation on an element of the same position in the vector of the operand, and a new vector is finally obtained. Specifically, if Vector<int> d1{1, 2, 3}, D2{4, 5, 6}, then, V1 + v2 equals {5, 7, 9}. Implementing such an operation does not look very difficult, and a very intuitive approach is as follows:

Vector<int> operator+ (const vector<int>& v1, Const vector<int>& v2) {
  //suppose v1.size () = = V2 . Size ()
  vector<int> R;

  R.reserve (V1.size ());
  for (Auto i = 0; i < v1.size (); ++i) {
    r.push_back (V1[i] + v2[i]);
  return r;
}

Similarly, you need to overload other operators
We overload each operator on a vector so that the vector's operations are the same as the general simple type, and the implementation is straightforward, but obviously there is a serious problem with this straightforward approach: inefficient. Efficiency is not high because of the whole operation, each step of the operation has produced intermediate results, and the intermediate result is a vector, so each time to allocate memory, if the participation of the vector is larger, and then the operation is relatively long, efficiency will be relatively low, there is no better way?

Since each operation produces intermediate results that can lead to efficiency problems, can you optimize the intermediate results? Looking back, the subtraction of this vector is not much different from the ordinary arithmetic, in the compiler principle, the evaluation of such expressions can usually be done by first turning the expression into a tree, and then by traversing the tree to get the final result, the computation of the result is accomplished once and does not need to preserve the intermediate state. For example, for expressions: V1 + v2 * V3, we can usually turn it into a tree as follows:

So the evaluation becomes a simple sequence traversal, so can our vector operations do the same?

An expression template

To remove the intermediate results, the key is to postpone the evaluation of the expression, but C + + does not support lazy evaluation, so you need to find ways to take these intermediate steps of expression and state, with a lightweight object to save, specifically, That is, you need to be able to encapsulate the operands of the intermediate steps of an expression and the type of operation so that you can perform these operations dynamically when needed, so that you define a class similar to the following:

Enum Optype {
  ot_add,
  ot_sub,
  Ot_mul,
  ot_div,
};

Class Vectmp {
  int type_;
  Const vector<int>& op1_;
  Const vector<int>& op2_;

Public:
  vectmp (int type, const vector<int>& OP1, const vector<int>& OP2)
    : Type_ (Type), Op1_ (OP1), op2_ (OP2) {}

  int operator[] (const int i) const {
    switch (type_) {case
      Ot_add:return op1_[i] + O P2_[i];
      Case Ot_sub:return Op1_[i]-op2_[i];
      Case Ot_mul:return Op1_[i] * op2_[i];
      Case Ot_div:return Op1_[i]/op2_[i];
      Default:throw "Bad type";}}
;

With this class, we can encapsulate the result of a simple operational expression into an object, and of course we have to overload the addition operator (and other operators) first:

Vectmp operator+ (const vector<int>& OP1, const vector<int>& OP2) {return
  vectmp (Ot_add, OP1, OP2);
}

So, for V1 + v2, we get a very lightweight vectmp object that can easily convert V1 + v2 results (traversing the operands in vectmp). However, the above approach can not deal with V1 + v2 * V3 such nested complex expression: V2 * V3 get a vectmp, that v1 + vectmp How to do it?

In the same way, we still have to put V1 + vectmp into a lightweight object, so it is best to save the operands in our vectmp can also be vectmp type, a bit of a recursive flavor ... With the template on it, you get the following code:

#include <vector> #include <iostream> using namespace std;

Enum Optype {ot_add, ot_sub, Ot_mul, Ot_div,};
  Template<class T1, Class t2> class Vecsum {optype type_;
  Const t1& op1_;
 Const t2& op2_; Public:vecsum (int type, const t1& OP1, const t2& OP2): Type_ (Type), op1_ (OP1), op2_ (OP2) {} int operator[
        ] (const int i) const {switch (TYPE_) {case Ot_add:return op1_[i] + op2_[i];
        Case Ot_sub:return Op1_[i]-op2_[i];
        Case Ot_mul:return Op1_[i] * Op2_[i];
        Case Ot_div:return Op1_[i]/op2_[i];
      Default:throw "Bad type";

}
    }
}; Template<class T1, Class t2> vecsum<t1, t2> operator+ (const t1& T1, const t2& T2) {return vecsum&lt ;
T1, t2> (ot_add, T1, T2); Template<class T1, Class t2> vecsum<t1, t2> operator* (const t1& T1, const t2& T2) {return vecsum
<t1, t2> (Ot_mul, T1, T2); int main () {std::vector<int> V1{1, 2, 3}, V2{4, 5, 6}, V3{7, 8, 9};
  Auto R = v1 + v2 * v3;
  for (Auto i = 0; i < r.size (); ++i) {std::cout << r[i] << "";

 }
}

The above code nicely solves the aforementioned efficiency issues, scalability is also good and non-invasive for vector, although the implementation may at first glance not very intuitive, in addition to this there are some minor problems can be more perfect:

Operator overloading is likely to affect other types, so it is best to limit the overloads to vectors and vectmp, which can be handled using Sfinae.

VecTmp Operator[] Function in the switch can be optimized, the vectmp template only need to add one parameter, and then the various types of operations to be biased.

VecTmpFor the saved operand is required, only vector or vectmp<>, and here should also use Sfinae to strengthen the restrictions, so that error information to look better.

Now let's take a look at this little odd piece of code, obviously the key is vectmp this class, we can find that its interface is actually very simple and straightforward, but its type can be so complex, for example, for V1 + v2 * V3 This expression, its result type is this: vectmp <vector<int>, Vectmp<vector<int>, Vector<int>>>, if the expression is more complex, its type is more complicated, if you look carefully, Did you find out where this thing looks like? Like a tree, a tree of a type.

The tree looks familiar, each leaf node is vector, and each internal node is instantiated by vectmp: This is a tree of a type that is determined at compile time. This complex type of expression at compile time has a learning name: Expression template. In C + + each expression must produce a result, and the result must have the type, the type is the compile-time thing, but the result is run-time. The final type of such an expression is determined by the combination of the corresponding types of results produced by each step of the operation, and the process of determining the type is in fact consistent with the recognition of the expression.

Vectmp object In fact is also a tree, its member variable op1_, op2_ is left and right son node, the tree's internal node represents an operation, the leaf node is the operand, and the sequence traversal, get the whole expression of the value.

The Magic boost::p Roto

Expression template is a good thing (just like expression Sfinae), it can help you build a very complex and playful type system at compile time (to achieve a lot of advanced gadgets, mainly functional). But obviously if everything needs to be written from scratch, this technology is still very troublesome to use, but the template metaprogramming is a very fun thing, there are many people have done a lot of pioneering work, see boost Proto Bar, in the C + + World open a door to the strange world

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.