boost::mpl::list 源码分析

使用 list 的方法如下:

#include <iostream> #include <boost/mpl/list/list10.hpp> #include <boost/mpl/size.hpp> using namespace boost; using namespace std; int _tmain(int argc, _TCHAR* argv[]) { typedef mpl::list3<int,double,int>::type r; cout<<mpl::size<r>::type::value<<endl; }

list3只能存放3个元素,如果要存放12(list12<...>)元素,那么头文件需要变成list20.hpp。

小于10等于10个元素都可以用头文件list10.hpp。

同时无需指定一个明确的值。比如:list<int,float,double...>等。同时相应的头文件也必须做出改变。

size函数求存放元素的个数。

 

这儿有两个版本的list(按生成方式的不同)。
一个是手工写成,另外一个依靠宏扩展而成。先讨论手工写成的list10.hpp。

#include <boost/mpl/list/list10.hpp>  包含的源码为:

 

#if !defined(BOOST_MPL_PREPROCESSING_MODE)//如果没有定义这个宏,就包括下面这个文件。 # include <boost/mpl/list/list0.hpp>//放在后面讨论 #endif #include <boost/mpl/aux_/config/use_preprocessed.hpp> 这个文件包括的源代码对宏BOOST_MPL_PREPROCESSING进行了定义,源码拷贝如下: #ifndef BOOST_MPL_AUX_CONFIG_USE_PREPROCESSED_HPP_INCLUDED #define BOOST_MPL_AUX_CONFIG_USE_PREPROCESSED_HPP_INCLUDED // Copyright Aleksey Gurtovoy 2000-2004 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // // See http://www.boost.org/libs/mpl for documentation. // $Id: use_preprocessed.hpp 49267 2008-10-11 06:19:02Z agurtovoy $ // $Date: 2008-10-11 02:19:02 -0400 (Sat, 11 Oct 2008) $ // $Revision: 49267 $ #define BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS //这句就是上面头文件的内容。 #endif // BOOST_MPL_AUX_CONFIG_USE_PREPROCESSED_HPP_INCLUDED 这儿我们先讨论手工写成的代码,而不是依靠宏扩展而成的代码,因此可以把 这个宏注释掉 #if !defined(BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS) / && !defined(BOOST_MPL_PREPROCESSING_MODE) //由于我们注释了这个宏,所以 //包括下面两个文件。 # define BOOST_MPL_PREPROCESSED_HEADER list10.hpp # include <boost/mpl/list/aux_/include_preprocessed.hpp> //下面这个版本是宏生成版本,暂时不考虑。先考虑手工代码。 #else # include <boost/preprocessor/iterate.hpp> namespace boost { namespace mpl { # define BOOST_PP_ITERATION_PARAMS_1 / (3,(1, 10, <boost/mpl/list/aux_/numbered.hpp>)) # include BOOST_PP_ITERATE() }} #endif // BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS #endif // BOOST_MPL_LIST_LIST10_HPP_INCLUDED   

 

 

这儿我们先讨论手工写成的代码,而不是依靠宏扩展而成的代码,因此可以把
上面那个BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS宏注释掉。

 

上面的include_preprocessed.hpp包含的源文件精简为:

# define AUX778076_HEADER / aux_/preprocessed/plain/BOOST_MPL_PREPROCESSED_HEADER / /**/ # include BOOST_PP_STRINGIZE(boost/mpl/list/AUX778076_HEADER)

 

BOOST_PP_STRINGIZE 宏定义在文件
#include <boost/preprocessor/stringize.hpp>中(当前编译器MSVC9.0)

代码精简为:

 

# define BOOST_PP_STRINGIZE(text) BOOST_PP_STRINGIZE_A((text)) # define BOOST_PP_STRINGIZE_A(arg) BOOST_PP_STRINGIZE_I arg # define BOOST_PP_STRINGIZE_I(text) #text //#text扩展成"text"


综上所述,

#include BOOST_PP_STRINGIZE(boost/mpl/list/AUX778076_HEADER)

全部展开为:
#include "boost/mpl/list/aux_/preprocessed/plain/list10.hpp"

 


下面分别举能存放一个元素,两个元素,三个元素的序列,其余的与此相似,不予讨论。
分别是list1、list2、list3。

template< typename T0 > struct list1 : l_item< long_<1> //这个参数代表size,指示能存放一个元素。下面定义 , T0 //这就是存放的那个元素。 , l_end > { typedef list1 type; }; template< typename T0, typename T1 > struct list2 : l_item< long_<2>//在下面定义。 , T0 , list1<T1> > { typedef list2 type; }; template< typename T0, typename T1, typename T2 > struct list3 : l_item< long_<3> , T0 , list2< T1,T2 > > { typedef list3 type; };

 

上面的long_定义如下:

 

//上面的long_定义如下: template<long N> struct long_ { static long value = N ; //当前的值 typedef long type; typedef long_ value_type; typedef integral_c_tag tag; //标记作用,在其他地方定义或是声明。 typedef long_<static_cast<long>(value+1)> next; //假如当前为:long_<1>,下一个就是long_<2> typedef long_<static_cast<long>(value-1)> prior;//假如当前内容为:long_<1>,上一个就是long_<0> // enables uniform function call syntax for families of overloaded // functions that return objects of both arithmetic ('int', 'long', // 'double', etc.) and wrapped integral types (for an example, see // "mpl/example/power.cpp") //对“()”进行重载返回当前的值,用法为:long_<5>(),这个值就是5,同上面的vaule 代表一个意思。 operator long() const { return static_cast<long>(this->value); } }; //static要在类外面定义。enum就不需要。 template<long N> long long_<N>::value;

 

基类l_item如下:

 

struct list_tag; //作为标记 //l_item的定义如下: template< typename Size //如果存放一个元素,从上面看来应该是long_<1>,两个是long_<2> , typename T , typename Next > struct l_item { // agurt, 17/jul/03: to facilitate the deficient 'is_sequence' implementation #if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)//vc7.0 版本 typedef int begin; //vc7才用这个版本 #endif typedef aux::list_tag tag;//aux是名词空间,list_tag在aux里面. typedef l_item type; typedef Size size;//list3对应long_<3>,list2对应long_<2>,list1对应long_<1> typedef T item; //当前的元素 typedef Next next; //下一个节点.list3的下一个节点是list2, list2 的下一个节点是list1. };

比较 mpl::vector和mpl::list的结构就可以看出:

因为这是元编程,运行都是O(1)时间,区别在于编译时间的不同。

这儿的编译时间和运行时时间的复杂度还是有区别的。只是用类似于运行时的时间复杂度来

衡量。在编译的时候,vector可以很随便的访问类中的任何一个元素,因为其中一种vector

的实现方式,实际是把每一个元素都写在了结构里面:item0,item1,item2,item3.....

而list则不同,list在访问首元素和尾元素倒是很快的。但是如果是中间的元素呢?只能通过迭代器来遍历,

这就像链表一样,一个节点一个节点的遍历。当然就是线性时间复杂度了:O(n)


迭代器

 

struct l_end //这个类起一个结束的标记作用。 { #if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)//vc7.0 版本 typedef int begin; #endif typedef aux::list_tag tag; typedef l_end type; typedef long_<0> size; }; struct l_iter_tag;//迭代器的标记 //迭代器标志。int_同long_一样。只是在long的地方用int来替换。 struct forward_iterator_tag : int_<0> { typedef forward_iterator_tag type; };


以上就是list的内容。下面讨论beginend 这两个迭代器对list是怎样实现的:

 

/* begin<l>::type 下面讨论begin算法怎样实习取元素的。 */ template< typename BOOST_MPL_AUX_NA_PARAM(Sequence) > struct begin { //sequence_tag这是一个标记. typedef typename sequence_tag<Sequence>::type tag_; typedef typename begin_impl< tag_ > //在下面定义。 ::template apply< Sequence >::type type; BOOST_MPL_AUX_LAMBDA_SUPPORT(1,begin,(Sequence)) }; template<> struct begin_impl< aux::list_tag > { template< typename List > struct apply //模板参数是list { //从下面可以看出l_iter定义里面并没有什么,关键信息是:List::type typedef l_iter<typename List::type> type; }; }; /* end<l>::type 指向 list 尾部的迭代器 */ template< typename BOOST_MPL_AUX_NA_PARAM(Sequence) // typename Sequence > struct end { typedef typename sequence_tag<Sequence>::type tag_; // typedef typename end_impl< tag_ > //end_impl全特化代码在下面。 ::template apply< Sequence >::type type; BOOST_MPL_AUX_LAMBDA_SUPPORT(1,end,(Sequence)) }; template<> struct end_impl< aux::list_tag > { template< typename > struct apply { typedef l_iter<l_end> type; //最后还是以l_end作为迭代器的参数。 }; }; //l_iter迭代调用如下, 最后 end<l>::type返回 l_iter<l_end>迭代器。 template< typename Node > struct l_iter { typedef aux::l_iter_tag tag; typedef forward_iterator_tag category; };

 


size(list) 算法:

size类源代码为:

template< typename BOOST_MPL_AUX_NA_PARAM(Sequence) > struct size : aux::msvc_eti_base< typename size_impl< typename sequence_tag<Sequence>::type > ::template apply< Sequence >::type >::type { };

size 继承 msvc_eti_base 类模板,

msvc_eti_base的源代码为:

 

template< typename T > struct msvc_eti_base : T { typedef T type; };

 

 

它继承模板参数,并以模板参数为type.

因此现在来看模板参数是什么:

template<> struct size_impl< aux::list_tag > { template< typename List > struct apply : List::size { }; };

size_impl的内嵌模板类apply,并没有type,但是上面的代码:::template apply< Sequence >::type

表明有type.这就是apply为什么要继承模板参数的原因,它可以访问基类的成员type。

这个type实际就是list。而获得了list这个类型就很容易的访问类里面的成员了。如果是

list3, 那么就可以访问size,而这儿的size就是long_<3>,对它求值long_<3>() = 3。

 

 

下面来看看list的tag(上面用到了):

template< typename BOOST_MPL_AUX_NA_PARAM(Sequence) > struct sequence_tag : aux::sequence_tag_impl< ::boost::mpl::aux::has_tag<Sequence>::value , ::boost::mpl::aux::has_begin<Sequence>::value >::template result2_<Sequence> { };

 

 它是继承sequence_tag_impl

template< bool has_tag_, bool has_begin_ > struct sequence_tag_impl { // agurt 24/nov/02: MSVC 6.5 gets confused in 'sequence_tag_impl<true>' // specialization below, if we name it 'result_' here template< typename Sequence > struct result2_; }; # define AUX_CLASS_SEQUENCE_TAG_SPEC(has_tag, has_begin, result_type) / template<> struct sequence_tag_impl<has_tag,has_begin> / { / template< typename Sequence > struct result2_ / { / typedef result_type type; / }; / }; / /**/ AUX_CLASS_SEQUENCE_TAG_SPEC(true, true, typename Sequence::tag) 这个宏推出以下的代码: template<> struct sequence_tag_impl<true,true> { template<typename Sequence> struct result2_ { typedef Sequence::tag type; }; }; AUX_CLASS_SEQUENCE_TAG_SPEC(true, false, typename Sequence::tag) 上面的宏推出: template<> struct sequence_tag_impl<true,false> { template<typename Sequence> struct result2_ { typedef Sequence::tag type; }; };

has_tag必须成功,才能得到正确的类型。它获得标记就是list的tag。

has_tag是由一个宏来实现的:

#define BOOST_MPL_HAS_XXX_TRAIT_DEF(name) / BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(BOOST_PP_CAT(has_,name), name, false) /

 

宏定义代码:

# elif BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1400)) / || BOOST_WORKAROUND(__IBMCPP__, <= 700) // MSVC 7.1+ & VACPP // agurt, 15/jun/05: replace overload-based SFINAE implementation with SFINAE // applied to partial specialization to fix some apparently random failures // (thanks to Daniel Wallin for researching this!) # define BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(trait, name, default_) / template< typename T > / struct BOOST_PP_CAT(trait, _msvc_sfinae_helper) / { / typedef void type; / };/ / template< typename T, typename U = void > / struct BOOST_PP_CAT(trait,_impl_) / { / BOOST_STATIC_CONSTANT(bool, value = false); / typedef boost::mpl::bool_<value> type; / }; / / template< typename T > / struct BOOST_PP_CAT(trait,_impl_)< / T / , typename BOOST_PP_CAT(trait, _msvc_sfinae_helper)< typename T::name >::type / > / { / BOOST_STATIC_CONSTANT(bool, value = true); / typedef boost::mpl::bool_<value> type; / }; / / template< typename T, typename fallback_ = boost::mpl::bool_<default_> > / struct trait / : BOOST_PP_CAT(trait,_impl_)<T> / { / }; / /**/

经过推导以后为:

template<typename T> struct has_tag__msvc_sfinae_helper { typedef void type; }; template< typename T, typename U = void > struct has_tag_impl_ { BOOST_STATIC_CONSTANT(bool, value = false); //bool static value = false; typedef boost::mpl::bool_<value> type; }; template< typename T > struct has_tag_impl_< T , typename has_tag__msvc_sfinae_helper< typename T::name >::type > { BOOST_STATIC_CONSTANT(bool, value = true); typedef boost::mpl::bool_<value> type; }; template< typename T, typename fallback_ = boost::mpl::bool_<default_> > struct trait : has_tag_impl_<T> { };

上面的mpl::bool_的代码为:

template< bool C_ > struct bool_ { BOOST_STATIC_CONSTANT(bool, value = C_); typedef integral_c_tag tag; typedef bool_ type; typedef bool value_type; operator bool() const { return this->value; } };

实际上就是指如果这个序列有tag标记就返回true,即使这个序列没有元素值仍然返回正确的

值:

AUX_CLASS_SEQUENCE_TAG_SPEC(true, true, typename Sequence::tag)//list在这种情况下,正确 AUX_CLASS_SEQUENCE_TAG_SPEC(true, false, typename Sequence::tag)//list, true AUX_CLASS_SEQUENCE_TAG_SPEC(false, true, nested_begin_end_tag)//list, false AUX_CLASS_SEQUENCE_TAG_SPEC(false, false, non_sequence_tag)//list, false

 

上面已经讨论了这些代码。

 

 

 

 

 

 


你可能感兴趣的:(list,struct,header,iterator,Class,include)