STL Source Code Analysis-implementation of extraction programming (traits) technology

Source: Internet
Author: User
Tags traits
1. why? By default, a template provides a single definition that can be used for any template parameters that you can think! However, for the person who writes the template, this method is not flexible, especially when the template parameter is a pointer, if you want to instantiate a parameter different from the type, it becomes impossible! Sometimes, it is impossible to disable the same instantiation! As a result, PartialSpecializatio

1. why?

By default, a template provides a single definition that can be used for any template parameters that you can think! However, for the person who writes the template, this method is not flexible, especially when the template parameter is a pointer, if you want to instantiate a parameter different from the type, it becomes impossible! Sometimes, it is impossible to disable the same instantiation! So it appears, Partial Specialization!

At the same time, when using the void * pointer, you can share code to the maximum extent and reduce code expansion!

2. what is it? In fact, it is user-defined features.Template <> is used to describe that this is a special version. a special version is designed for parameters of any template type to make further condition restrictions!To put it bluntly, it isSome heavy-duty priority selection mechanisms, Select the most appropriate bitwise template for instantiation!

3. Significance of Partial Specialization: We provide a special version for the general design (that is, some template parameters in the general version are explicitly specified to influence the template instantiation type );

4. one of its applications in STL: Traits programming techniques. The core point is to instantiate a template, whether it is a class instantiation template, a pointer, or a pointer to a constant, the types of template submission are all in line with program requirements !!! Therefore, Traits is also called a "feature extraction machine" by Mr. Hou Jie (you can hand over the correct element type for both types and pointers )!

5. without the special feature, there will be no widespread use of the so-called Traits. without Traits, STL may not be a treasure of C ++, without stl nb, C ++ may not be the language leader! It is precisely because of its small specialization that the iterator has made great achievements and separated the algorithm from the data structure!

1. the Traits programming techniques are described in the previous article!

2. a good use is in the iterator;

3. Why? The premise is that not all template types are class type, some are native pointers, but some point to const T *

However, typedef T value_type cannot be used to extract the correct element type;

4. whether it is a native pointer int * or const int *, you can use traits to retrieve the correct value_type;

5. it is the indirect layer of traits that separates algorithms from data structures! This makes the iterator a binder so that STL can work together!

6. therefore,Iterator_traits must be designed with a special version when the input type is pointer and pointer to const!

Introduction

The extract programming technology is used in STL,

Brief description of extraction technology STL in iterator

STL (Standard Template Library) is a set builder of C ++ Generic Programming (template technology). iterator plays an important role in STL. There are three important concepts in STL:

  1. Containers, including sequential containers (vector,list) And associated containers (map,set)
  2. Algorithm, function templates for various operations on containers (count,count_if)
  3. The iterator serves as a bridge between algorithms and containers, allowing algorithms to develop independently of containers.

The important function of the iterator is to decouple the container and algorithm, or to decouple the data and Operation. The algorithm uses the iterator as the input to get rid of the access to the specific container data. the container-generated iterator is used to traverse every element in the container and avoid exposing the internal data structure and implementation details of the container.

Here, an example of an algorithm is used to demonstrate the usage of the iterator:

template 
  
   Iterator find(Iterator begin, Iterator end, const T& value){while (begin != end && *begin != value)++begin;return begin;}
  

Note the algorithm shown in this example.find()Can be used in a variety of containers (vector,map...), If there is no iterator, you need to implementfind()Algorithm.

Simple iterator

In the implementation of the iterator, you often need to access the type of the object referred to by the iterator.value type. Use embedded type statementtypedefYou can easily hide the object type, as shown in the following iterator:

templates 
  
   struct Iterator {typedef T value_type;...};
  

Generic algorithms can passtypename Iterator::value_typeTo obtainvalue type.

template 
  
   typename Iterator::value_typegetValue(Iterator iter) {return *iter;}
  

Note keywordstypenameBecauseTIstemplateThe compiler does not know the parameter before it is instantiated.TIs it a type or another object,typenameIt is used to tell the compiler that this type can be compiled.

Concept of extraction

In a simple iterator, the internal details of the object indicated by the embedded type declaration are well hidden and data and algorithms are separated. However, STL requires support for the iterator algorithms, native pointers should also be supported, such

Int array[4] = {1, 2, 3, 4};find(array, array+4, 3);

One problem exists here is that native pointers cannot be embedded with type declarations, so there is a need for multiple layers of encapsulation, and the extraction compilation technology came into being.
Traits programming technology is classified into four words: feature extraction. In the context of the iterator, the value type of the iterator is extracted. it can be conceptually considered that the type of the object referred to by the iterator is a feature of the iterator (traits)

template 
  
   struct iterator_traits {typedef typename Iterator::value_type value_type;...};
  

Withiterator_traitsTo rewrite the algorithm.getValue():

template 
  
   typename iterator_traits
   
    ::value_typegetValue(Iterator iter) {return *iter;}
   
  

The advantage of multi-layer encapsulation is that,iterator_traitsIs a C ++ class template, which can be customized for native pointers (special iterators). < <泛型思维> > The template is biased towards (any) templateThe parameter is further restricted by a specially designed version, while the native pointer T*, const T*Is a kind of special.

template 
  
   struct iterator_traits
   
     {typedef T value_type;};template 
    
     struct iterator_traits
     
       {typedef T value_type;};
     
    
   
  

Whether the iterator is a custom class template or a native pointer (T*,const T*),struct iterator_traitsCan extract the correct value type

STL iterator

Value type is only a feature of the iterator (traits). In practice, the STL iterator defines a total of five features. in order to make the user-defined iterator suitable for STL algorithms, STL makes a convention to write a base classstd::teratorAs long as the custom iterator inheritsstd::iterator,iterator_traitsWe can extract all the features of the iterator correctly, so that the custom iterator can be integrated into the STL family and use a variety of generic algorithms seamlessly:

Template <class Category, class Value, class Distance = ptrdiff_t, class Pointer = Value *, class Reference = Value &> struct iterator {typedef Category; typedef Value value_type; typedef Distance difference_type; typedef Pointer pointer; typedef Reference reference;}; the corresponding struct is defined as follows: template <class Iterator> struct {typedef typename Iterator: value_typevalue_type; typedef typename Iterator: difference_type struct; typedef typename Iterator: pointer; typedef typename Iterator: reference; typedef typename Iterator: iterator_category;}; template <class T> struct iterator_traits
 
  
{Typedef T value_type; typedef ptrdiff_t difference_type; typedef T * pointer; typedef T & reference; typedef extends iterator_category ;}; template <class T> struct iterator_traits
  
   
{Typedef T value_type; typedef ptrdiff_t difference_type; typedef const T * pointer; typedef const T & reference; typedef random_access_iterator_tag iterator_category ;};
  
 

The above iterators involve four other features, which are limited by space and will not be described. interested readers will read the references below.

Type extraction

The extraction (traits) programming technology makes upC++HoweverSTLIt only regulates the characteristics of the iterator and developsiterator_traits. Since this technology is so useful, it should be applied to more extensive application scenarios. sgi stl (STL version developed by the Silicon Graphics System) has made an attempt to apply it outside the world of the iterator, therefore, the concept of type extraction is generated.

We know that,C++Custom types have many features, such as constructor, copy constructor, and Destructor. on the other hand,C++Built-in type integerint,longNo constructor, copy constructor, and Destructor. based on these features, we can use the most effective measures to construct and assign values. for example, for built-in types, we do not need to call constructor or copy constructor, but directly use memory processing (malloc(),memcpy()) To achieve the highest efficiency, which significantly improves the performance of large-scale and frequently-operated containers.

Simple example

To use these features in the type, you can define a feature extraction machine for the type:__type_traits

struct __true_type {};struct __false_type {};Template 
  
   struct __type_traits {typedef __false_type has_trivial_default_constructor;typedef __false_type has_trivial_destructor;};
  

Because embedded type declarations cannot represent true or false, we define struct here__true_typeAnd__false_type. By default, these features are based on the most conservative values. then, based on the specific situation, the template is used to set a more optimistic value for the specific type. for example, the built-in int type definition template is special:

template <>struct __type_traits
  
    {typedef __true_type has_trivial_default_constructor;typedef __true_type has_trivial_destructor;};
  

According to < > Introduction: Some compilers can analyze various types of programs and generate corresponding __type_traitTemplate specialization. of course, for compilers that do not support this function, manually compile the template specialization to define a more optimistic value. Otherwise, the default value __false_typeWill take effect.

Sgi stl extraction

Defined by SGI STL__type_traitsIn addition to the featureshas_trivial_default_constructorAndhas_trivial_destructorAnd other features, as described below:

Template
   
    
Struct _ type_traits {typedef _ true_type sequence; // You can customize typedef _ false_type sequence for special compilers; typedef _ false_type has_trivial_copy_constructor; typedef _ false_type sequence; typedef _ false_type has_trivial_destructor ;};
   
Application scenario-copy

Template functionscopy()YesSTLA generic algorithm has many special templates to improve the performance in different scenarios. we hope to use the method of Raytheon in appropriate cases to achieve the highest performance, for example, for different types, depending on whether there is a copy constructor, it can have different operations:

// Copy an array whose elements are of any type. use the most effective copying method template as appropriate.
   
    
Inline void copy (T * source, T * destination, int n) {copy (source destination, n, typename _ type_traits
    
     
: Has_trivial_copy_constructor ();} // copy an array. the element type is not trival copy constructorstemplate.
     
      
Void copy (T * source, T * destination, int n, _ false_type) {...} // copy an array whose element type has trival copy constructorstemplate
      
       
Void copy (T * source, T * destination, int n, _ true_type ){...}
      
     
    
   
Application scenario-Destructor in the memory pool

In the implementation of the memory pool, the acquisition and release of the object's memory space are required. In general, to release the dynamic memory space of an object, you need to call the destructor of the object, therefore, you can define the destructor template.destruct()To execute the destructor. on the other hand, if the object does not require the destructordestuct()Do nothing.

Template
   
    
Void destruct (T & t) {typedef typename type_traits
    
     
: Has_trivial_destrutor has_trivial_destructor; __destruct (t, has_trivial_destructor ();} template
     
      
_ Destruct (T & t, _ ture_type) {// destructor T} template
      
       
_ Destruct
       
      
     
    
   
Applying extract technology to convert enumeration type to real type

In actual code writing, we often encounter this situation: an enumeration constant is known to obtain the corresponding real type, which can be solved by extraction technology, such as defining an enumeration constant:

Typedef enum FieldType {struct = 0, struct, struct, FIELDTYPE_INT16, struct, FIELDTYPE_INT32, FIELDTYPE_UINT32, FIELDTYPE_INT64, struct, struct, FIELDTYPE_DOUBLE, FIELDTYPE_CSTRING,} EFieldType; the extraction technology can be used to define the extraction machine VariableTypeTraits to obtain the actual type corresponding to the enumeration type: template
   
    
Struct VariableTypeTraits {typedef void SyntaxType ;};
   


The preceding meaning indicates that ifptHas a featurevoid, You can useVariableTypeTraits ::SyntaxType voidExtracted. Of course, the above module is just an empty shell, because for different enumeration typesVariableTypeTraits ::SyntaxType ExtractvoidIs meaningless. In this case, the template features come in handy. through the template features, you can define the corresponding types for each enumeration type:

# Define VARIABLE_TYPE_TRAITS_HELPER (pt, type) \ template <> \ struct VariableTypeTraits
   
    
\{\ Typedef type SyntaxType ;\}; extract (bytes, int8_t) values (bytes, uint8_t) values (FIELDTYPE_INT16, int16_t) values (bytes, uint16_t) values (FIELDTYPE_INT32, int32_t) struct (FIELDTYPE_UINT32, uint32_t) substring (FIELDTYPE_INT64, int64_t) substring (struct, uint64_t) substring (FIELDTYPE_FLOAT, float) substring (FIELDTYPE_DOUBLE, double) in order to avoid repeated code, the macro-defined implementation method is used. after defining the preceding content, you can easily obtain the actual type pointed to by the enumeration constant: void Fun (FieldType ft) {switch (ft) {case FIELDTYPE_INT32: typedef VariableTypeTraits
    
     
: SyntaxType syntaxType; syntaxType foo ;...}
    
   

}Sample code

First, I will organize the code snippets in the previous article into a complete program to deepen the reader's understanding of this usage.

// Traits_example1.cpp # include
    
     
# Include
     
      
# Include
      
       
// Enumeration type definition typedef enum FieldType {FIELDTYPE_UNDEFINED = 0, FIELDTYPE_INT8, FIELDTYPE_INT32, // to simplify the problem, only list two} EFieldType; // use the Traits programming skills template
       
        
Struct VariableTypeTraits {typedef void SyntaxType ;}; template <> struct VariableTypeTraits
        
         
{Typedef int8_t SyntaxType ;}; template <> struct VariableTypeTraits
         
           {Typedef int32_t SyntaxType ;}; // test the demo function void func (int8_t var) {fprintf (stdout, "type: int8_t; value: % d \ n", var );} void func (int32_t var) {fprintf (stdout, "type: int32_t; value: % d \ n", var);} int main () {typedef VariableTypeTraits
          
            : SyntaxType int8_type; int8_type int8_a = 1; func (int8_a); typedef VariableTypeTraits
           
             : SyntaxType int32_type; int32_type int32_ B = 2; func (int32_ B); return 0 ;}
           
          
         
        
       
      
     
    
Convert a real type to an enumeration type

Similarly, the extraction technology can be used to convert the real type to the enumeration type:

template 
    
     struct TypeTraits {static const FieldType FIELD_TYPE = FIELDTYPE_UNDEFINED;}
    

Note that the nested type statement cannot be used here (typedef), Because the enumerated variables are objects rather than types, the static constants of the class are used to define them.FIELD_TYPENext, you can define template-specific for each type without the template-specific type.FILED_TYPE=FIELDTYPE_UNDEFINED

#define TYPE_TO_FIELDTYPE(type, field_type) \template<> \struct TypeTraits
    
      { \static const FieldType FIELD_TYPE = field_type; \};TYPE_TO_FIELDTYPE(int8_t, FIELDTYPE_INT8);TYPE_TO_FIELDTYPE(uint8_t, FIELDTYPE_UINT8);TYPE_TO_FIELDTYPE(int16_t, FIELDTYPE_INT16);TYPE_TO_FIELDTYPE(uint16_t, FIELDTYPE_UINT16);TYPE_TO_FIELDTYPE(int32_t, FIELDTYPE_INT32);TYPE_TO_FIELDTYPE(uint32_t, FIELDTYPE_UINT32);TYPE_TO_FIELDTYPE(int64_t, FIELDTYPE_INT64);TYPE_TO_FIELDTYPE(uint64_t, FIELDTYPE_UINT64);TYPE_TO_FIELDTYPE(float, FIELDTYPE_FLOAT);TYPE_TO_FIELDTYPE(double, FIELDTYPE_DOUBLE);
    

It is also relatively simple to use.TypeTraits ::FIELD_TYPE You can getintEnumeration type corresponding to the typeFIELDTYPE_INT32

Summary

To sum up, there are two main advantages of traits programming skills.

  1. You can upgrade the judgment by using "features" to the compilation level, rather than the runtime. This improves the performance.
  2. Universal implementation and data decoupling can be achieved


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.