As mentioned in the previous article, the Concepts Check in sgi stl is actually a feature that will be checked during compilation by using template class instantiation. sgi stl is widely used.
Concepts Check, as mentioned earlier, is not mentioned here. in <C ++ Primer>, the template features are described in the "template and generic programming" section.
Template features are divided into two types: 1. Absolute features
2. Some Features
In this blog post, we mainly look at some special features. We still use the stl_stack.h source code.
template <class _Tp, class _Sequence __STL_DEPENDENT_DEFAULT_TMPL(deque<_Tp>) >
Macro _ STL_DEPENDENT_DEFAULT_TMPL is simply used to specify the default template parameters:
# define __STL_DEPENDENT_DEFAULT_TMPL(_Tp) = _Tp
Let's look at the source code of these two lines in the Stack template class implementation:
__STL_CLASS_REQUIRES(_Sequence, _BackInsertionSequence);
What are the things of the _ STL_CLASS_REQUIRES macro below?
#define __STL_CLASS_REQUIRES(__type_var, __concept) \ typedef void (* __func##__type_var##__concept)( __type_var ); \ template <__func##__type_var##__concept _Tp1> \ struct __dummy_struct_##__type_var##__concept { }; \ static __dummy_struct_##__type_var##__concept< \ __concept##_concept_specification< \ __type_var>::__concept##_requirement_violation> \ __dummy_ptr_##__type_var##__concept
This macro is similar to the _ STL_CLASS_REQUIRES_SAME_TYPE macro explained above. You can see it in the Stack according to the _ BackInsertionSequence parameter to be checked.
To find the source code:
template <class _BackInsertionSequence>struct _BackInsertionSequence_concept_specification {static void_BackInsertionSequence_requirement_violation(_BackInsertionSequence __s) { // Refinement of Sequence _Sequence_concept_specification<_BackInsertionSequence>::_Sequence_requirement_violation(__s); // Valid Expressions _ERROR_IN_STL_SEQ::__back_function_requirement_violation(__s); _ERROR_IN_STL_SEQ::__push_back_function_requirement_violation(__s); _ERROR_IN_STL_SEQ::__pop_back_function_requirement_violation(__s);}
There is a static function in the template. The function first calls another static function defined in the _ Sequence_concept_sepcification template _ Sequence_requirement_violation
struct _Sequence_concept_specification {static void_Sequence_requirement_violation(_Sequence __s) { // Refinement of ForwardContainer _ForwardContainer_concept_specification<_Sequence>::_ForwardContainer_requirement_violation(__s); // Refinement of DefaultConstructible _DefaultConstructible_concept_specification<_Sequence>::_DefaultConstructible_requirement_violation(__s); // Valid Expressions _ERROR_IN_STL_SEQ::__fill_constructor_requirement_violation(__s); _ERROR_IN_STL_SEQ::__fill_default_constructor_requirement_violation(__s); _ERROR_IN_STL_SEQ::__range_constructor_requirement_violation(__s); _ERROR_IN_STL_SEQ::__insert_function_requirement_violation(__s); _ERROR_IN_STL_SEQ::__fill_insert_function_requirement_violation(__s); _ERROR_IN_STL_SEQ::__range_insert_function_requirement_violation(__s); _ERROR_IN_STL_SEQ::__erase_function_requirement_violation(__s); _ERROR_IN_STL_SEQ::__range_erase_function_requirement_violation(__s); _ERROR_IN_STL_SEQ::__front_function_requirement_violation(__s);}
Whether it is _ BackInsertionSequence_concept_specification or _ Sequence_concept_specification, Sequence Concept Check is completed through _ ERROR_IN_STL_SEQ
Static Method completion: provides the source code for the two static methods in _ BackInsertionSequence_concept_specification using _ ERROR_IN_STL_SEQ:
template <class _XX> static void __push_back_function_requirement_violation(_XX& __s) { typename _XX::value_type __t = typename _XX::value_type(); __s.push_back(__t); } template <class _XX> static void __pop_back_function_requirement_violation(_XX& __s) { __s.pop_back(); }
I have posted so many source codes, talked about the ideas, and haven't analyzed a piece of code. Next I will briefly analyze this simple code.
_ Push_back_function_requirement_violation create an object _ t in the static method, and then call the input type _ s (which is traced back to the previous _ Sequence in the Stack)
Push_back method. during compilation, if an error occurs when _ t is created and the push_back method is called, an alarm is reported.
The _ pop_back_function_requirement_violation method is similar.
In _ BackInsertionSequence_concept_specification, the static method in _ Sequence_concept_specification is called to see what has been done.
In addition to calling the static method check in _ ERROR_IN_STL_SEQ, The _ ForwardContainer_concept_specification and
_ Defaconconstructible_concept_specification. The two template classes are in the Container_concepts.h file. The source code is as follows:
template <class _ForwardContainer>struct _ForwardContainer_concept_specification {static void_ForwardContainer_requirement_violation(_ForwardContainer __c) { // Refinement of Container _Container_concept_specification<_ForwardContainer>::_Container_requirement_violation(__c); // Requirements on Iterators typedef typename _ForwardContainer::iterator iter; typedef typename _ForwardContainer::const_iterator const_iter; _ForwardIterator_concept_specification<const_iter>::_ForwardIterator_requirement_violation(const_iter()); _Mutable_ForwardIterator_concept_specification<iter>::_Mutable_ForwardIterator_requirement_violation(iter());}};
(Only the source code of _ ForwardContainer_concept_specification is provided .)
Like Sequence Check, _ ForwardContainer_concept_specification also calls the static method in the _ Container_concept_specification template,
Then, _ Container_concept_specification calls the static method in _ ERROR_IN_STL_CONTAINER to execute Container Concept Check.
So let's look at the static method in _ ERROR_IN_STL_CONTAINER.
template <class _Container> static void __empty_function_must_be_const(const _Container& __c) { __c.empty(); } template <class _Container> static void __empty_function_requirement_violation(_Container& __c) { __c.empty(); __empty_function_must_be_const(__c); } template <class _Container> static void __swap_function_requirement_violation(_Container& __c) { __c.swap(__c); }
The analysis is very simple. Like the above, it is to execute a method check for the parameter _ Sequence in the Stack. If _ Sequence does not exist in these methods, it will fail during the compilation period.
Here we can say it is clearer than the previous article. But it is not enough because sgi stl not only executes these checks. Why?
Let's take a look at the source code in _ ForwardContainer_requirement_violation:
typedef typename _ForwardContainer::iterator iter; typedef typename _ForwardContainer::const_iterator const_iter; _ForwardIterator_concept_specification<const_iter>::_ForwardIterator_requirement_violation(const_iter()); _Mutable_ForwardIterator_concept_specification<iter>::_Mutable_ForwardIterator_requirement_violation(iter())
Another static method in the template class is called. Don't worry about the trouble. Let's take a look at it again. _ ForwardIterator_concept_specification source code:
template <class _ForwardIterator>struct _ForwardIterator_concept_specification {static void_ForwardIterator_requirement_violation(_ForwardIterator __i) { // Refinement of InputIterator _InputIterator_concept_specification<_ForwardIterator>:: _InputIterator_requirement_violation(__i);}
We can see that other static methods in the template class are called to perform the check .....
To be honest, I can see that this is a bit speechless... the SGI STL check is divided into many levels, and it is very complicated. But let's keep reading it ~
Finally, we will find that the static methods for executing Iterator and other trivial checks are provided by _ STL_ERROR.
Now let's look at the static method in _ STL_ERROR.
template <class _Type> static _Type __default_constructor_requirement_violation(_Type) { return _Type(); } template <class _Type> static _Type __copy_constructor_requirement_violation(_Type __a) { _Type __c(__a); return __c; }
The preceding section checks the default constructor and copy constructor.
template <class _Iterator> static void __preincrement_operator_requirement_violation(_Iterator __i) { ++__i; } template <class _Iterator> static void __postincrement_operator_requirement_violation(_Iterator __i) { __i++; }
Pre-auto-increment and post-increment check.
In addition, throughout the process, there is a macro _ sink_unused_warning in all struct that provides static method detection. This macro exists to eliminate the compiler's warning about unused variables.
...
...
Okay, here we will introduce the sgi stl source code for the partial special check during the compilation period. if the description is incomplete, please give a reasonable explanation in the comments. I will take it seriously.
"Even if there are thousands of songs from afar on my way"
"Even if the stars shine over the moon tonight"