I believe that most people who use STL are using containers in it. programmers who use vector, list, and map are very familiar with the following code: vector I _v;
I _v.push_back (1 );
I _v.push_back (2 );
I _v.push_back (3 );
I _v.push_back (4 );
I _v.push_back (5 );
It's boring, right? The assignment library of boost makes this process much simpler:
# Include "Boost/assign/STD/vector. HPP"
Using namespace boost: Assign;
Vector I _v;
I _v + = 1, 2, 4, 5;
The effect is the same as that of the above program, but the readability is much better. It looks a bit like a "script language.
For associated containers, there are similar cleaning methods:
# Include "Boost/assign/list_inserter.hpp"
# Include "string"
Using namespace STD;
Using namespace boost: Assign; Map months;
Insert (months)
("January", 31) ("February", 28)
("March", 31) ("maid", 30)
("May", 31) ("June", 30)
("July", 31) ("August", 31)
("September", 30) ("October", 31)
("November", 30) ("December", 31 );
Analyze the source code of assign. Take vector as an example. Let's look at it first:
// Assign/STD/vector. HPP:
Template <Class V, Class A, class V2>
Inline list_inserter <assign_detail: call_push_back <STD: vector>, V>
Operator + = (STD: vector & C, V2 V)
...{
Return push_back (c) (v );
}
Operator + = has been overloaded. Its task is to return a list_inserter class, which is one of the core classes in assign. Let's look at push_back again. It does not have any substantive action, just creates a list_inserter and returns it.
Template <Class C>
Inline list_inserter <assign_detail: call_push_back,
Boost_deduced_typename C: value_type>
Push_back (C & C)
...{
Static boost_deduced_typename C: value_type * p = 0;
Return make_list_inserter (assign_detail: call_push_back (C), P );
}
Here, call_push_back (c) actually creates an instance of the class call_push_back so that the generated list_inserter can know how to perform the operation.
Template <Class C>
Class call_push_back
...{
C & C _; public: call_push_back (C & C): C _ (c)
...{}
Template <class T> void operator () (t r)
...{
C _. push_back (R );
}
};
Make_list_inserter is similar to make_pair in STL and is used for packaging implementation classes. The real implementation is to use list_inserter.
Template <class function, class argument>
Inline list_inserter <function, argument>
Make_list_inserter (function fun, argument *)
...{
Return list_inserter <function, argument> (fun );
}
List_inserter is overloaded with the + = Operator, so I _v + = 1, 2, 3, 4, and 5. The push_back function returns a list_inserter. In this example, I _v + = 1 is changed to push_back (I _v) (1), where push_back (I _v) (Note: does not include the following "(1 )"!) Changed to make_list_inserter (call_push_back (I _v), 0). Finally, make_list_inserter returns the list_inserter <call_push_back, int> instance. Now you can add the following "(1, because the list_inserter overload the "()" operator, the value of 1 is received by list_inserter.
Then how do we deal with the comma between numbers? Do not remember that STD: cout <1 <2 <3; here <and the comma in assign is actually a truth. The <operator returns an iostream, the comma operator returns a list_inserter. The "+ =" operator returns the first list_inserter, And the other comma "follow-up ":
Template <class function, class argument = assign_detail: forward_n_arguments>
Class list_inserter
...{
List_inserter (function fun): insert _ (fun)
...{}
....
List_inserter & operator ()()
...{
Insert _ (argument ());
Return * this;
}
Template <class T>
List_inserter & operator, (const T & R)
...{
Insert _ (R );
Return * this;
}
PRIVATE: function insert _;
}
Here insert _ is the previous assign_detail: call_push_back (c), so insert _ (R) is assign_detail: call_push_back (C) (R ).
List_inserter and repeat, repeat_fun, range and other methods correspond to the implementation of I _v + = 1, repeat (2, 4), 3... In assign respectively. This is basically the case for assign for vector. As for the assign of MAP and other containers, the implementation is similar to this.