Use
The list method is as follows:
# Include <iostream> <br/> # include <boost/MPL/LIST/list10.hpp> <br/> # include <boost/MPL/size. HPP> <br/> using namespace boost; <br/> using namespace STD; <br/> int _ tmain (INT argc, _ tchar * argv []) <br/>{< br/> typedef MPL: list3 <int, double, int >:: type R; <br/> cout <MPL :: size <r >:: type: value <Endl; <br/>}< br/>
List3 can only store three elements. If you want to store 12 (list12 <...>) elements, the header file must be changed to list1_hpp.
The header file list10.hpp can be used for 10 or less elements.
You do not need to specify a specific value. For example, list <int, float, double...>. At the same time, the corresponding header file must be changed.
The size function calculates the number of elements to store.
Here there are two versions of list (based on the generation method ).
One is manually written, and the other is extended by macros. First, we will discuss the manually written list10.hpp.
# Include <boost/MPL/LIST/list10.hpp>
The source code is:
# If! Defined (boost_mpl_preprocessing_mode) // if this macro is not defined, the following file is included. <Br/> # include <boost/MPL/LIST/list0.hpp> // discussed later <br/> # endif <br/> # include <boost/MPL/aux _/ config/use_preprocessed.hpp> <br/> the source code included in this file defines the macro boost_mpl_preprocessing, source code copy is as follows: <br/> # ifndef resume <br/> # define resume <br/> // copyright Aleksey gurtovoy 2000-2004 <br/> // distributed under the boost Software License, Version 1.0. <br/> // (see accompanying file license_00000.txt or copy at <br/> // http://www.boost.org/LICENSE_1_0.txt) <br/> // see http://www.boost.org/libs/mpl for documentation. <br/> // $ ID: use_preprocessed.hpp 49267 06: 19: 02z agurtovoy $ <br/> // $ Date: 02:19:02-0400 (SAT, 11 Oct 2008) $ <br/> // $ revision: 49267 $ <br/> # define boost_mpl_1__no_preprocessed _ Headers // the content of the header file above. <Br/> # endif // boost_mpl_aux_config_use_preprocessed_hpp_included <br/> here we will first discuss the code written by hand, instead of the Code extended by macros, therefore, you can comment out the macro <br/> # If! Defined (boost_mpl_assist_no_preprocessed_headers)/<br/> &&! Defined (boost_mpl_preprocessing_mode) // because we have commented on this macro, <br/> // contains the following two files. <Br/> # define boost_mpl_preprocessed_header list10.hpp <br/> # include <boost/MPL/LIST/aux _/include_preprocessed.hpp> <br/> // the following version is a macro version, not considered for the moment. Consider manual code first. <Br/> # else <br/> # include <boost/Preprocessor/iterate. HPP> <br/> namespace boost {namespace MPL {<br/> # define boost_pp_iteration_params_1/<br/> (3, (1, 10, <boost/MPL/LIST/aux _/numbered. HPP>) <br/> # include boost_pp_iterate () <br/>}< br/> # endif // boost_mpl_1__no_preprocessed_headers <br/> # endif/else
Here we will first discuss the code written manually, instead of the Code extended by macros.
Comment out the boost_mpl_cfg_no_preprocessed_headers macro above.
The above include_preprocessed.hpp contains the following source files:
# Define aux778076_header/<br/> aux _/preprocessed/plain/<br/>/**/<br/> # include boost_pp_stringize (boost/MPL/LIST/aux778076_header)
Boost_pp_stringize macro is defined in the file
# Include <boost/Preprocessor/stringize. HPP> (current compiler msvc9.0)
The code is simplified:
# Define boost_pp_stringize (text) boost_pp_stringize_a (text) <br/> # define boost_pp_stringize_a (ARG) boost_pp_stringize_ I Arg <br/> # define parse (text) # text // # Extend text to "text" <br/>
To sum up,
# Include boost_pp_stringize (boost/MPL/LIST/aux778076_header)
Expand All:
# Include "Boost/MPL/LIST/aux _/preprocessed/plain/list10.hpp"
The following describes the sequence of three elements that can store one element, two elements, and so on. The rest are similar and will not be discussed.
List1, list2, and list3.
Template <br/> typename t0 <br/> struct list1 <br/>: rochelle item <br/> long _ <1> // This parameter represents the size, indicating that an element can be stored. <Br/>, t0 // is the stored element. <Br/>, Rochelle end <br/> <br/>{< br/> typedef list1 type; <br/> }; <br/> template <br/> typename T0, typename t1 <br/> struct list2 <br/>: rochelle item <br/> long _ <2> // is defined below. <Br/>, t0 <br/>, list1 <t1> <br/>{< br/> typedef list2 type; <br/> }; <br/> template <br/> typename T0, typename T1, typename t2 <br/> struct list3 <br/>: rochelle item <br/> long _ <3> <br/>, t0 <br/>, list2 <t1, t2> <br/>{< br/> typedef list3 type; <br/> };
The preceding long _ is defined as follows:
// The preceding long _ is defined as follows: <br/> template <long n> <br/> struct long _ <br/>{< br/> static long value = N; // current value <br/> typedef long type; <br/> typedef long _ value_type; <br/> typedef integral_c_tag tag; // tag function, define or declare it elsewhere. <Br/> typedef long _ <static_cast <long> (Value + 1)> next; // if the current value is long _ <1>, next is long _ <2> <br/> typedef long _ <static_cast <long> (value-1)> prior; // if the current content is long _ <1>, the previous one is long _ <0> <br/> // enables uniform function call syntax for families of overloaded <br/> // functions that return objects of both Arithmetic ('int', 'long', <br/> // 'double', etc .) and wrapped integral types (for an example, see <br/> // "MPL/ Example/power. CPP ") <br/> // reload" () "to return the current value. Usage: long _ <5> (). The value is 5, the preceding vaule indicates a meaning. <Br/> operator long () const {return static_cast <long> (this-> value) ;}< br/> }; <br/> // static must be defined outside the class. Enum is not required. <Br/> template <long n> <br/> long _ <n>: value;
The base class Rochelle item is as follows:
Struct list_tag; // as the tag <br/> // The definition of l_item is as follows: <br/> template <br/> typename size // If an element is stored, from the above, it should be long _ <1>, two are long _ <2> <br/>, typename T <br/>, typename next <br/> struct l_item <br/> {<br/> // agurt, 17/JUL/03: to facilitate the deficient 'is _ Sequence 'Implementation <br/> # If boost_workaround (boost_msvc, <= 1300) // version of vc7.0 <br/> typedef int begin; // This version is used for vc7 <br/> # endif <br/> typedef aux: list_tag tag; // aux is a noun space, and list_tag is in AUX. <br/> typedef l_item type; <br/> typedef size; // list3 corresponds to long _ <3>, list2 corresponds to long _ <2>, list1 corresponds to long _ <1> <br/> typedef t item; // The current element <br/> typedef next; // The next node. the next node of list3 is list2, And the next node of list2 is list1. <br/> };
Comparing the MPL: vector and MPL: List structures, we can see that:
Because this is metaprogramming, the runtime is O (1) time, the difference is that the compilation time is different.
The Compilation Time and runtime time are different here. It just uses the time complexity similar to the runtime.
Measurement. During compilation, the vector can be any element of the struct class, because one of the Vector
Actually, every element is written in the structure: item0, Item1, item2, item3 .....
The list is different, and the first and last elements of the list are quickly accessed. But what if it is an intermediate element? It can only be traversed by the iterator,
This is like a linked list, where one node is traversed by one node. Of course it is linear time complexity: O (N)
Iterator
:
Struct l_end // This class plays an end flag. <Br/>{< br/> # If boost_workaround (boost_msvc, <= 1300) // vc7.0 <br/> typedef int begin; <br/> # endif <br/> typedef aux: list_tag tag; <br/> typedef l_end type; <br/> typedef long _ <0> size; <br/>}; <br/> struct l_iter_tag; // iterator flag <br/> // iterator flag. Int _ is the same as long. Only int is used to replace long. <Br/> struct forward_iterator_tag: int _ <0> {typedef forward_iterator_tag type ;};
The above is the content of the list. As discussed belowBegin
AndEnd
How the two iterators implement the list:
/* </P> <p> begin <L>: Type <br/> The following describes how the begin algorithm gets elements. <Br/> */<br/> template <br/> typename boost_mpl_aux_na_param (sequence) <br/> struct begin <br/> {// sequence_tag this is a tag. <br/> typedef typename sequence_tag <sequence >:: type tag _; <br/> typedef typename begin_impl <tag _> // is defined below. <Br/>:: template apply <sequence >::: Type type; <br/> boost_mpl_aux_lambda_support (1, begin, (sequence) <br/> }; <br/> template <> <br/> struct begin_impl <aux :: list_tag> <br/>{< br/> template <typename list> struct apply // The template parameter is list <br/>{// from the following we can see that there is no what, key Information: List: Type <br/> typedef l_iter <typename list: type> type; <br/> }; <br/>/* <br/> end <L>: type indicates the iterator at the end of the list. <br/> */<br/> templa Te <br/> typename boost_mpl_aux_na_param (sequence) // typename sequence <br/> struct end <br/>{< br/> typedef typename sequence_tag <sequence >:: type tag _; // <br/> typedef typename end_impl <tag _> // The full-featured code of end_impl is listed below. <Br/>:: template apply <sequence >::: Type type; <br/> boost_mpl_aux_lambda_support (1, end, (sequence) <br/> }; <br/> template <> <br/> struct end_impl <aux :: list_tag> <br/>{< br/> template <typename> struct apply <br/>{< br/> typedef l_iter <l_end> type; // Finally, Rochelle end is used as the iterator parameter. <Br/>}; <br/> // The Rochelle ITER iteration call is as follows. End <L >:: type returns the Rochelle ITER <l_end> iterator. <Br/> template <typename node> <br/> struct l_iter <br/> {<br/> typedef aux: l_iter_tag tag; <br/> typedef forward_iterator_tag category; <br/> };
Size (list) algorithm:
Size class source code:
Template <br/> typename boost_mpl_aux_na_param (sequence) <br/> struct size <br/>: aux :: msvc_eti_base <br/> typename size_impl <typename sequence_tag <sequence >:: type> <br/>:: template apply <sequence >:: type <br/> :: type <br/>{</P> <p> };
Size inherits the msvc_eti_base class template,
The source code of msvc_eti_base is:
Template <typename T> struct msvc_eti_base <br/>: T <br/>{< br/> typedef T type; <br/> };
It inherits the template parameters and uses the template parameters as type.
So now let's look at the template parameters:
Template <> <br/> struct size_impl <aux: list_tag> <br/>{< br/> template <typename list> struct apply <br/>: List :: size <br/>{< br/>}; <br/> };
Size_impl embedded template class apply, there is no type, but the above Code:: Template apply <sequence >::: Type
Indicates the type. This is why apply inherits the template parameters. It can access the type of the base class member.
This type is actually a list. If the list type is obtained, it is easy for the Members in the category class. If yes
List3, then you can access the size, and the size here is long _ <3>, evaluate it as long _ <3> () = 3.
Let's take a look at the list tag (used above ):
Template <br/> typename boost_mpl_aux_na_param (sequence) <br/> struct sequence_tag <br/>: aux: sequence_tag_impl <br/>: boost:: MPL: aux: has_tag <sequence >:: value <br/>,: boost: MPL: aux: has_begin <sequence> :: value <br/>:: template result2 _ <sequence> <br/>{< br/> };
It inherits sequence_tag_impl
Template <bool has_tag _, bool has_begin _> <br/> struct sequence_tag_impl <br/>{< br/> // agurt 24/NOV/02: msvc 6.5 gets confused in 'sequence _ tag_impl <true> '<br/> // specialization below, if we name it 'result _ 'Here <br/> template <typename sequence> struct result2 _; <br/>}; <br/> # define aux_class_sequence_tag_spec (has_tag, has_begin, result_type)/<br/> template <> struct sequence_tag_impl <pas_tag, has_begin>/<br/> {/<br/> template <typename sequence> struct result2 _/<br/>{/ <br/> typedef result_type type; /<br/>};/<br/>/**/<br/> aux_class_sequence_tag_spec (true, true, typename sequence: Tag) <br/> This macro introduces the following code: <br/> template <> struct sequence_tag_impl <true, true> <br/>{< br/> template <typename sequence> struct result2 _ <br/>{< br/> typedef sequence: tag type; <br/>}; <br/> aux_class_sequence_tag_spec (true, false, typename sequence: Tag) <br/> the macro above is introduced as follows: <br/> template <> struct sequence_tag_impl <true, false> <br/>{< br/> template <typename sequence> struct result2 _ <br/>{< br/> typedef sequence: tag type; <br/>}; <br/> };
Has_tag must be successful to obtain the correct type. It obtains the tag of the list.
Has_tag is implemented by a macro:
# Define boost_mpl_has_xxx_trait_def (name)/<br/> boost_mpl_has_xxx_trait_named_def (boost_pp_cat (has _, name), name, false )/
Macro definition code:
# Elif boost_workaround (boost_msvc, boost_tested_at (1400)/<br/> | boost_workaround (_ ibmcpp __, <= 700) <br/> // msvc 7.1 + & vacpp <br/> // agurt, 15/Jun/05: replace overload-based sfinae implementation with sfinae <br/> // applied to partial specialization to fix some apparently random failures <br/> // (thanks to Daniel Wallin for researching this !) <Br/> # define partition (trait, name, default _)/<br/> template <typename T>/<br/> struct boost_pp_cat (trait, _ msvc_sfinae_helper) /<br/>{/ <br/> typedef void type;/<br/>};/<br/> template <typename t, typename u = void>/<br/> struct boost_pp_cat (trait, _ impl _)/<br/>{/ <br/> boost_static_constant (bool, value = false ); /<br/> typedef boost: MPL: bool _ <value> type;/<br/> }; /<br/> template <typename T>/<br/> struct boost_pp_cat (trait, _ impl _) </<br/> T/<br/>, typename boost_pp_cat (trait, _ msvc_sfinae_helper) <typename T: Name> :: type/<br/> {/<br/> boost_static_constant (bool, value = true);/<br/> typedef boost: MPL :: bool _ <value> type;/<br/>};/<br/> template <typename T, typename fallback _ = boost: MPL :: bool _ <default _>/<br/> struct trait/<br/>: boost_pp_cat (trait, _ impl _) <t>/<br/>{/ <br/>};/<br/> /**/
After derivation:
Template <typename T> <br/> struct has_tag _ msvc_sfinae_helper <br/>{< br/> typedef void type; <br/> }; <br/> template <typename T, typename u = void> <br/> struct has_tag_impl _ <br/>{< br/> boost_static_constant (bool, value = false ); // bool static value = false; <br/> typedef boost: MPL: bool _ <value> type; <br/> }; <br/> template <typename T> <br/> struct has_tag_impl _ <br/> T <br/>, typename has_tag _ msvc_sfinae_helper <typename T: Name>:: Type <br/> <br/>{< br/> boost_static_constant (bool, value = true); <br/> typedef boost: MPL :: bool _ <value> type; <br/>}; <br/> template <typename T, typename fallback _ = boost: MPL :: bool _ <default _> <br/> struct trait <br/>: has_tag_impl _ <t> <br/>{< br/> };
The above MPL: bool _ code is:
Template <bool C _> struct bool _ <br/>{< br/> boost_static_constant (bool, value = C _); <br/> typedef integral_c_tag tag; <br/> typedef bool _ type; <br/> typedef bool value_type; <br/> operator bool () const {return this-> value ;}< br/> };
In fact, if the sequence has tag tags, true is returned, even if the sequence does not have element values, true is returned.
Value:
Aux_class_sequence_tag_spec (true, true, typename sequence: Tag) // In this case, the list is correct <br/> aux_class_sequence_tag_spec (true, false, typename sequence: Tag) // list, true <br/> aux_class_sequence_tag_spec (false, true, nested_begin_end_tag) // list, false <br/> values (false, false, non_sequence_tag) // list, false
The Code has been discussed above.