meet-dream

boost::graph的名字参数

        初见boost的名字参数,给人一种“惊为天人”的感觉,没想到在c++中还能写出如此优雅的令人震撼的代码。boost的名字参数采用的是C++的范型来实现的,全部在编译期完成名字到参数的定位,没有RTTI,没有运行时开销,不需要任何元数据。她依旧沿袭了C++的高效原则,带来的缺点就是无法跨二进制代码使用。当然boost的名字参数不是拿出来炫耀C++的强大能力的,要看c++编译期的强大能力,boost.MPL才能让人忍不住挺身呐喊。她的主要目的是简化graph library的复杂的函数差数调用.动则数十个参数的函数调用,必须遵循严格的调用顺序让人头痛不已(还让人活吗?要么自己写一套算法?!),名字参数就像一个天使来到人间,她是如此的优雅,迷人,让人心醉(不要流口水!),从此,有了她的C++程序员都过上了幸福的生活!
       假设有下面的函数 
       void fun(T1 t1,T2   t2,T3* t3=0,.. ,T20* t20=0); 
         其中后十个参数是可选的,如果你想给t20传入一个非缺省值,那么看起来你要给所有的函数参数赋值才能通过编译了。肯定没人愚蠢到用排列组合的方式来添加N个函数给用户使用吧。怎么办呢?想不出来,不要紧,假设boost.graph有这样一个类似的函数,我们先看看她是如何调用这个函数的,关键是学到的东西要能发挥作用,给人以良好的感觉 
         fun(t1,t2,Param<T20*>(&T20()));
       当然,这只是一个看起来和她机制一样的而又较简单,容易理解的方式。够简单吧,不要惊讶,其实说起来,她的原理还是很简单的,只是要自己实作一个作品还是有点难度。为了实现boost.graph,专门做了一个相对简单的property map库,在她的基础上建立了针对boost.graph名字参数系统,其实这一套机制可以用在更宽泛的库中,不知道为什么没有放出来。boost.graph的实作看起来令人生畏:visitor,named_param,class_generator,Python bindings,她的每种技术都可以让人够研究好一段时间。我们就用简单的例子来说明名字参数的原理,不是严格按她的类来组织的。
          先看同名成员变量是如何访问的。 
           
struct B
{
  
string val;
}

struct D:B
{
   
int val;
}

         看下面的访问函数
          D d; d.val=100;//OK          D::val=100
          d.val="10";//error D::val (int) can't assign with a string
          //but we can access it by
          ((B).d).val="10"; 
         如果我们能绕过这个问题,问题就完成了一大半了,其实方法很简单。即使给每个参数加个名字,有了名字以后,我们就可以找到对应的项,也不会有类型冲突的问题发生。 
         
  struct no_param{};
   
struct B:no_param
  {
   typename name_B name; 
   
string val;
  };
  template
<class B>
  
struct D:B
  {
     typedef B 
base;
     typename name_D name;
     
int val;
  };
  
//假设下面的模版会传入<D,name_B>
 template<typename propertys,typename tag>
  
struct select
  {
     typedef  if_else
<                                                    //select second type if first return true,else third
                     if_same<property::name,tag>::value,       // D::name!=name_B ,false
                     property,                                              //
                     select<property::base,tag>::type>          //recurive call select,will pass <B,name_B>,this call will success return B
                    >::type type;                                         //get the third type,it return B,so type is defined as B
  }

       这样一来,我们就可以根据名字访问B的变量val了
       ((select::type)(d)).val="success";
       虽然boost.graph的名字系统比这个复杂多了,但万变不离其宗,其原理是一样的。如此奇妙的东西竟然建立在如此简单的机制上,可见只有想不到的东西,没有做不到的东西这句话还是有一定道理的,更印证了那句"简单就是美"的名言. 
         下次继续分析boost.graph的visitor机制.
   


//if_same and if_else 
template<class T1,class T2>
struct if_same
{
 
enum{value=false};
};
template
<class T>
struct if_same<T,T>
{
 
enum{value=true};
}
template
<bool value,class T1,class T2>
struct if_else
{
 typedef T1 type;
}

template
<class T1,class T2>
struct if_else<false,T1,T2>
{
 typedef T2 type;
}


   

posted on 2007-05-28 17:08 meet-dream 阅读(1459) 评论(5)  编辑 收藏 引用 所属分类: boost library

评论

# re: boost::graph的名字参数 2007-05-28 17:13 meet-dream

如果有热心人,
弱弱的问一下,你们是如何排版的?
我发了几次都是乱码!!  回复  更多评论   

# re: boost::graph的名字参数 2007-05-28 17:30 danielwyo

不是乱码, 是没有排版, 看起来好烦.

  回复  更多评论   

# re: boost::graph的名字参数 2007-05-28 17:39 on-the-fly

有个插入代码的按钮的,找找看  回复  更多评论   

# re: boost::graph的名字参数 2007-05-28 17:40 梦在天涯

使用插入代码工具,可惜啊不知道里面就是没有专门支持C++的哦,我一般都是使用C#的哦,
  回复  更多评论   

# re: boost::graph的名字参数 2007-05-29 09:32 zenith

o.....  回复  更多评论   


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理