This article is taken in the documentation in Boost. It is not very good, but it has already begun to translate the index to complete it. The translation of itself can be more bad. Don't smash me.
My website: taowen.cn.st
Generic Programming Techniques Fit Programming Technology
This Is An Incomplete Survey of Some of The Generic Programming Techniques Used in The Boost Libraries.
This is an incomplete observation of certain type programming techniques used in the BOOST library.
Table of contents
table of Contents
Introduction the anatomy of a conceptory tag dispatch adaptors Type Generator Object Generators Policy Classes
Introduction
Introduction
Generic programming is about generalizing software components so that they can be easily reused in a wide variety of situations. In C , class and function templates are particularly effective mechanisms for generic programming because they make the generalization possible without sacrificing efficiency.
Valer Programming is a generalization software component that makes them reused programming techniques in a wide range of cases. In C , class and function templates are especially efficient mechanisms for norm-like programming because they do this generalization without sacrificing efficiency.
AS A Simple Example of Generic Programming, WE WILL LOOK Ath How One Might Generalize The Memcpy () Function of The C Standard Library. An Implementation of Memcpy () Might Look Like The Following:
As a simple example of the model programming, we will see how the Memcpy function in the C standard library. One implementation of Memcpy may look like this:
Void * Memcpy (Void * Region1, Const Void * Region2, Size_t N)
{
Const char * first = (const char *) Region2;
Const char * last = (const char *) region2) N;
Char * result = (char *) Region1;
While (first! = last)
* Result = * first ;
Return Result;
}
The memcpy () function is already generalized to some extent by the use of void * so that the function can be used to copy arrays of different kinds of data. But what if the data we would like to copy is not in an array? Perhaps it is in a linked list. Can we generalize the notion of copy to any sequence of elements? Looking at the body of memcpy (), the function's minimal requirements are that it needs to to traverse through the sequence using some sort of pointer, access elements pointed to, write the elements to the destination, and compare pointers to know when to stop. The C standard library groups requirements such as these into concepts, in this case the Input Iterator concept (for region2) and the Output Iterator concept (for Region1). Thememcpy function has been generalized to some extent through the use of VOID *. The function can be used to copy arrays of any type of data. But if we want to copy the data is not in an array? It may be in a linked list. Can we generalize this concept of any element sequence? Take a look at Memcpy's function, the minimum requirement required is to use some pointer overhead sequence, access the pointed element, and compare the pointer to know when it is stopped. The C standard library is classified as a concept in this case, in this case, Input Iterator concept Output Iterator concept.
If we rewrite the memcpy () as a function template, and use the Input Iterator and Output Iterator concepts to describe the requirements on the template parameters, we can implement a highly reusable copy () function in the following way:
If we rewrive Memcpy as a function template and use the Input Iterator and Output Iterator concept to describe the requirements for template parameters, we can use a high-reserved COPY function:
Template
OutputIterator
Copy (InputITerator First, InputItemrator Last, OutputIterator Result)
{
While (first! = last)
* Result = * first ;
Return Result;
}
Using the generic copy () Function, We can now Elements from any Kind of Sequence, Including a Linked List That Exports Iterators Such as std :: list. Using the version of the COPY function, we can now copy from any kind of sequence Elements, including linked lists for Iterators, like std :: list.
#include
#include
#include
int main ()
{
Const int N = 3;
Std :: Vector
Std :: List
Region2.push_back (1);
Region2.push_back (0);
Region2.push_back (3);
Std :: copy (region2.begin (), region2.end (), region1.begin ());
For (int i = 0; i Std :: Cout << Region1 [i] << " Std :: cout << std :: endl; } Anatomy of a concept Concept analysis A concept is a set requirements, where the requirements consist of valid expressions, associated types, invariants, and complexity guarantees. A type that satisfies the set of requirements is said to model the concept. A concept can extend the requirements of another concept, which Is Called Refinement. A concept is a collection of requests, including effective expressions, related types, invaridation, and complexity assurance. A type that satisfies such a set of requirements is known as the concept of molding. A concept can expand another concept request, which is called Refinement. Valid Expressions Are C Expressions Which Must Compile SuccessFully For the Objects Involved in The Expression To Be Considered Models of The Concept. Valid expression is a C expression that must successfully compile. For models included in the expression included in the expression. Associated Types are types that are related to the modeling type in that they participate in one or more of the valid expressions. Typically associated types can be accessed either through typedefs nested within a class definition for the modeling type, or they are accessed through a traits Class. Related Types is the type associated with modeling, where the type appears in one or more effective expressions. Typical related types can be either passing TypeDef in the Class definition of molded types. Invariants are run-time characteristics of when the objects that must always be true, that is, the functions involving the objects must preserve these characteristics. The invariants often take the form of pre-conditions and post-conditions. Invariants objects running Nature, must always be true. That is, the functions in the object must be protected these properties. Invariants often in the form of pre-condition and a post-condition of Complexity Guarantees are maximum limits on how long the execution of one of the valid expressions will take, or how much of various resources its computation will use. Complexity to ensure effective expression of One of the execution time of the formula, or how much the maximum upper limit of the consumed resources The Concepts Used In The C Standard Library Are Documented At The SGI STL Site. The concept used in the C standard library has a document on the SGI STL website. Traits . A traits class provides a way of associating information with a compile-time entity (a type, integral constant, or address) For example, the class template std :: iterator_traits A Traits Class provides a method of associating information and a compile time entity. For example, class template std :: itemarator_traits looks like this: Template Struct iterator_traits { TYPEDEF ... ITERATOR_CATEGORY; TYPEDEF ... VALUE_TYPE; Typedef ... Difference_Type; Typedef ... Pointer; TYPEDEF ... REFERENCE; } The Traits' Value_Type Gives Generic Code The Type Which The Iterator is "Pointing At", while the iterator_category can be used to select More Efficient Algorithms Depending on the iterator's capabilities. TRAITS "Value_Type" provides a model code for the type of Iterator's current pointing, which can be used to select more efficient algorithms based on the ability of Iterator. A key feature of traits templates is that they're non-intrusive: they allow us to associate information with arbitrary types, including built-in types and types defined in third-party libraries, Normally, traits are specified for a particular type by ( Partially) Specializing the traits template. A key feature of the Traits Template is that they are non-inserted: they allow us to associate information and any type together, including built-in types and defined types defined in the third party library, general, traits pass (part) Specify Traits Template to specify the specific type For an in-depth description of std :: iterator_traits, see this page provided by SGI. Another very different expression of the traits idiom in the standard is std :: numeric_limits To view the depth description of std :: itemarator_traits, refer to the page provided by this SGI. In another standard, the very different expressions of Traits Idiom are std :: numeric_limits Tag dispatching A technique that often goes hand in hand with traits classes is tag dispatching, which is a way of using function overloading to dispatch based on properties of a type. A good example of this is the implementation of the std :: advance () function in the C Standard Library, which increments an iterator n times. Depending on the kind of iterator, there are different optimizations that can be applied in the implementation. If the iterator is random access (can jump forward and backward arbitrary distances), then the advance () function can simply be implemented with i = n, and is very efficient: constant time Other iterators must be advanced in steps, making the operation linear in n If the iterator is bidirectional, then it makes sense for n to be.. NEGATIVE, SO WE MUST DECIDE WHETER TO INCREMENT OR DECREMENT The Iterator. The technology used by traits is Tag Dispatching. It is a different type of use of function overload to assign calls based on the same attribute. One of this technology is a very good implementation is the Std :: Advance function in the C standard library, which makes an iterator step n times. Depending on the type of iterator, it can be applied to different optimizations. If the iterator is Random Access (can jump any distance forward and backward), the Advance function can be implemented simply with i = n, and it is very efficient: constant time. Other iterators must be divided by n steps, making the operation as linear. If the iterator is bidirectional, then it makes N can be a negative number, so we must decide whether to make the iterator step or step. The relation between tag dispatching and traits classes is that the property used for dispatching (in this case the iterator_category) is often accessed through a traits class. The main advance () function uses the iterator_traits class to get the iterator_category. It then makes a call the the overloaded advance_dispatch () function. The appropriate advance_dispatch () is selected by the compiler based on whatever type the iterator_category resolves to, either input_iterator_tag, bidirectional_iterator_tag, or random_access_iterator_tag. A tag is simply a class whose only purpose is to convey some property for Use in tag dispatching and similar techniques. Refer to this Page for a More Detailed Description of Iterator Tags.tag Dispatching and Traits Class The relationship between class is used to assign the attribute (Iterator_category in this case) often by a traits class. Come. The main function of Advance () uses the Iterator_Traits class to get item_category. Then it calls an overloaded Advance_Dispatch, determines the specific overload version based on the type of Iterator_Category parsing (Resolve). Iterator_category either INPUT_ITERATOR_TAG either bidirectional_iterator_tag either random_access_iterator_tag. Tag is a class that is only used to communicate some attributes used in Tag Dispatching or similar technologies. Refer to this page to get a more specific description of Iterator Tags. Namespace std { Struct Input_iterator_tag {}; Struct Bidirectional_Item_tag {}; Struct random_access_iterator_tag {}; Namespace detail { Template Void Advance_Dispatch (InputITerator & I, Distance N, Input_iterator_tag) { While (n--) i; } Template Void Advance_Dispatch (BidirectionAritrator & i, Distance N, Bidirectional_iterator_tag) { IF (n> = 0) While (n--) i; Else While (N ) --I; } Template Random_access_iterator_tag) { i = n; } } Template Void Advance (INPUTITERATOR & I, DISTANCE N) { TypeName Iterator_Traits Detail :: Advance_Dispatch (i, n, category); } } Adaptors Adapter An adaptor is a class template which builds on another type or types to provide a new interface or behavioral variant. Examples of standard adaptors are std :: reverse_iterator, which adapts an iterator type by reversing its motion upon increment / decrement, and std :: Stack, Which Adapts a Container to Provide A Simple Stack Interface. The adapter is a class template based on other types or multiple types to provide a new interface or different behavior. Examples of standard equipment are std :: REVERSE_ITERATOR and Std :: Stack. Std: Reverse_iterator It comes with an iterator by reversing its movement in step increasing and walking. Std :: Stack Gets a container to provide a simple stack interface. A More Comprehensive Review of The Adaptors in The Standard Can Be Found Here. A more in-depth review of the adapter in the standard can be found here Type generators A type generator is a template whose only purpose is to synthesize a new type or types based on its template argument (s) [1]. The generated type is usually expressed as a nested typedef named, appropriately type. A type generator is usually used To Consolidate a Complicated Type Expression Into A Simple One, AS in Boost :: Filter_Iterator_generator, Which Looks Something Like this: Type Generator is a template for synthesizing one or more new types based on its template parameters. The synthetic type is often represented by a type of nature of Nested TypeDef. A Type Generator is often used to turn a complex type expression into a simple thing, just like Boost :: Filter_Iterator_genegerator. It is probably this: Template Class value = COMPLICATED DEFAULT, Class Reference = complicated default, Class Pointer = Complicated Default, Class Category = COMPLICATED DEFAULT, Class Distance = Complicated Default > Struct filter_iterator_generator { TypedEf Iterator_Adaptor < Iterator, Filter_Iterator_Policies Value, Reference, Pointer, Category, Distance> Type } Now, That's Complicated, But Producing An Adapted Filter Iterator Is Much Easier. You can USUALLY JUST WRITE: Now, although Generator itself is complicated but created a matching Filter Iterator easier. You can usually write just this: Boost :: filter_iterator_generator Object generators An object generator is a function template whose only purpose is to construct a new object out of its arguments. Think of it as a kind of generic constructor. An object generator may be more useful than a plain constructor when the exact type to be generated is difficult or impossible to express and the result of the generator can be passed directly to a function rather than stored in a variable. Most Boost object generators are named with the prefix "make_", after std :: make_pair (const T &, const U &) . Object Generator is a function template that creates an object based on its parameters. Take it as a model of constructor. When the exact type to be generated is difficult or completely impossible, the Generator's structure can be passed directly to a function instead of being stored in a variable, an Object Generator may be more useful than a normal constructor. Most Boos Object Generators are named with Make_ prefix, just like std :: make_pairt (const t &, const u ". For example, given: For example, give it: Struct widget { Void TWEAK (int); } Std :: vector By Chaining Two Standard Object Generators, Std :: bind2nd () and Std :: MEM_FUN (), We can Easily Tweak all widgets: By putting two standard Object Generator, std :: bind2nd and std :: mem_fun, chain in one, we can easily screw all Widgets: Void Tweak_all_widgets1 (int Arg) { For_each (widget_ptrs.begin (), widget_ptrs.end (), Bind2nd (std :: mem_fun (& widget :: tweak), arg); } WITHOUT Using Object Generators The Example Above Would Would Would Would Would Love Do not use Object Generator, the above example may look like this: Void Tweak_all_widgets2 (int Arg) { For_each (struct_ptrs.begin (), struct_ptrs.end (), Std :: Binder2nd Std :: MEM_FUN1_T } AS Expressions Get More Complicated The Need To Reduce The Verbosity of Type Specification Gets More Compelling. When the expression is more complex, the lengthy requirements of mitigation type description becomes more urgent. Policy Classes A Policy Class Is A Template Parameter Used to Transmit Behavior. An Example From The Standard Library IS Std :: Allocator, Which Supplies Memory Management Behaviors To Standard Containers. A template parameter for propagating behavior when a policy class. An example from the standard library is std :: allocator, which provides memory management for standard containers. Policy Classes Have Been Explored in detil by Andrei Alexandrescu in this paper. He Writes: The Policy class is deeply explored in this article in Andrei Alexandrescu. He wrote: Policy classes are implementations of punctual design choices. They are inherited from, or contained within, other classes. They provide different strategies under the same syntactic interface. A class using policies is templated having one template parameter for each policy it uses. This allows the User to select the policies needed. The Policy class is a strict design is an implementation. They inherit or include other classes from other classes. They provide different strategies on the basis of the same syntactic interface. A class that uses the policy provides a template parameter for each policy it uses. This makes users choose the strategy they need. The power of policy classes comes from their ability to combine freely. By combining several policy classes in a template class with multiple parameters, one achieves combinatorial behaviors with a linear amount of code. The power of the Policy class comes from their free combination. By combining several POLICY classes in a template class, the behavior of providing a combination in linear numbers is implemented. Andrei's description of policy classes describe their power as being derived from their granularity and orthogonality. Boost has probably diluted the distinction in the Iterator Adaptors library, where we transmit all of an adapted iterator's behavior in a single policy class. There is precedent for this, However: std :: char_traits, despite its name, acts as a policies class, determines the behaviors of st :: basic_string. Andrei's description of the Policy class Description Their power comes from their granularity and orthogonality. Boost may have diluted the difference in the Iterator Adaptor library, and we propagate all Adapted Iterator's behavior in a policy class. However, this has a precedent: std :: char_traits, regardless of its name, just like a Policy class acts as a behavior of std :: basic_string. Notes [1] Type Generators Are A Workaround for the lack of `` Templated Typedefs '' In C . Type Generator is supplemented to make up for the lack of "parameterized typedef" in C .