Modern C ++ design note Chapter 2 Chapter 2. Techniques

Source: Internet
Author: User
The amazing effect is still going on. The second chapter begins to talk about some basic traditional techniques (but I still don't know, some new help is provided by using the special compilation features of template compilation.
What is impressive is compile-time assertions, and traits.
Assert
It is a very strange thing. To be honest, it is a little useful in debugging, because in release, if assert fails to throw an error dialog box, it will not make at all.
Sense. However, it is also a good choice to help you find errors during crash programming and compilation during debugging. So I had this idea.
In fact, this compile-time assertions is not a very new thing. Let's look at the Loki implementation in it:

Namespace Loki
{
//////////////////////////////////////// ////////////////////////////////////////
// Helper structure for the static_check macro
//////////////////////////////////////// ////////////////////////////////////////

Template Struct compiletimeerror;
Template <> struct compiletimeerror
{};
}

//////////////////////////////////////// ////////////////////////////////////////
// Macro static_check
// Invocation: static_check (expr, ID)
// Where:
// Expr is a compile-time integral or pointer expression
// ID is a C ++ identifier that does not need to be defined
// If expr is zero, ID will appear in a compile-time error message.
//////////////////////////////////////// ////////////////////////////////////////

# Define loki_static_check (expr, MSG )/
{LOKI: compiletimeerror <(expr )! = 0)> error _ # MSG; (void) Error _ # MSG ;}

Its
Implement this to Loki: compiletimeerror <(expr )! =
0)> this step is enough, but if error _ # is added, it will be more descriptive. A similar implementation in boost is called
Boost_static_assert. If you are interested, check it.

Let's talk about playing this assert. Let's take a look at traits, which has a classic application in STL. Scott Mayer's comment is quoted here:Traits
Are basically compile-time else-if-thens: The unspecialized template is
The else clause, the specializations are the if clses. I think traits
Can be used to determine whether a template parameter is a built-in
Type. Also whether a template parameter inherits from a given Base
Class. The trick is to create a template generating code that won't
Compile, then provide specializations that * will * compile for
Special cases that are allowed.
Traits is called a compiler-based
Select if-else (the topic of this chapter is to do as much dynamic as possible during compilation ). Use the template's partial
Specification can be used to complete the instantiation for specific types during compilation, and find the most efficient implementation. Here we post a bit of
Partial definition of iterator_traits in STL:

// Template class iterator_traits
Template Struct iterator_traits
{// Get traits from iterator _ ITER
Typedef typename _ ITER: iterator_category;
Typedef typename _ ITER: value_type;
Typedef typename _ ITER: difference_type;
Typedef difference_type distance_type; // retained
Typedef typename _ ITER: pointer;
Typedef typename _ ITER: Reference reference;
};

Template Struct iterator_traits <_ ty>
{// Get traits from pointer
Typedef random_access_iterator_tag iterator_category;
Typedef _ ty value_type;
Typedef ptrdiff_t difference_type;
Typedef ptrdiff_t distance_type; // retained
Typedef _ ty * pointer;
Typedef _ ty & reference;
};

Template Struct iterator_traits
{// Get traits from const pointer
Typedef random_access_iterator_tag iterator_category;
Typedef _ ty value_type;
Typedef ptrdiff_t difference_type;
Typedef ptrdiff_t distance_type; // retained
Typedef const _ ty * pointer;
Typedef const _ ty & reference;
};

Template <> struct iterator_traits <_ bool>
{// Get traits from Integer type
Typedef _ int_iterator_tag iterator_category;
Typedef _ bool value_type;
Typedef _ bool difference_type;
Typedef _ bool distance_type;
Typedef _ bool * pointer;
Typedef _ bool & reference;
};

Template <> struct iterator_traits
{// Get traits from Integer type
Typedef _ int_iterator_tag iterator_category;
Typedef char value_type;
Typedef char difference_type;
Typedef char distance_type;
Typedef char * pointer;
Typedef char & reference;
};

Template <> struct iterator_traits
{// Get traits from Integer type
Typedef _ int_iterator_tag iterator_category;
Typedef signed Char value_type;
Typedef signed Char difference_type;
Typedef signed Char distance_type;
Typedef signed Char * pointer;
Typedef signed Char & reference;
};

The definition here is incomplete, but we can see some clues,The iterator_traits class has a lot of partial specification definitions. Here we have pointers, const pointers, Char, bool, etc. It is obvious that pointer, A type such as value_type produces a good definition due to different types, so as to optimize and implement different types. If we are looking at a function's
Template inline
Typename iterator_traits <_ init>: difference_type
_ Clrcall_or_cdecl distance (_ init _ first, _ init _ last)
{// Return distance between iterators
Typename iterator_traits <_ init>: difference_type _ off = 0;
_ Distance2 (_ first, _ last, _ off, _ iter_cat (_ First ));
Return (_ off );
}
Note the _ iter_cat function of this function. Here is its implementation:
Template inline
Typename iterator_traits <_ ITER >:: iterator_category
_ Clrcall_or_cdecl _ iter_cat (const _ ITER &)
{// Return category from iterator argument
Typename iterator_traits <_ ITER >:: iterator_category _ cat;
Return (_ cat );
}
Actually, the returned type is the iterator_category type of the original _ first iterator_traits <_ init>. Multiple implementations can be implemented based on different types:
Template inline
Void _ clrcall_or_cdecl _ distance2 (_ ranit _ first, _ ranit _ last, _ diff & _ off,
Random_access_iterator_tag)
{// Add to _ off distance between random-access iterators

# If _ has_iterator_debugging
If (_ first! = _ Last)
{// Check for null pointers
_ Debug_pointer (_ First );
_ Debug_pointer (_ last );
}
# Endif/* _ has_iterator_debugging */

_ Off + = _ last-_ first;
}

Template inline
Void _ clrcall_or_cdecl _ distance2 (_ init _ first, _ init _ last, _ diff & _ off,
Input_iterator_tag)
{// Add to _ off distance between input iterators
For (; _ first! = _ Last; ++ _ First)
++ _ Off;
}
Template inline
Void _ clrcall_or_cdecl _ distance2 (_ fwdit _ first, _ fwdit _ last, _ diff & _ off,
Forward_iterator_tag)
{// Add to _ off distance between forward iterators (redundant)
For (; _ first! = _ Last; ++ _ First)
++ _ Off;
}
What we can see is that random access is much more efficient than others. These iterator functions in STL are believed to use such traits type judgment to achieve the most suitable function for the current type, but to achieve the most efficient.

In fact, this is just a little bit of Application of traits. I believe there are more and more powerful traits applications in Loki in the course of reading this book, which should be presented slowly. Programming is really an art!

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.