loop_in_codes

低调做技术__欢迎移步我的独立博客 codemaro.com 微博 kevinlynx

让人无语的boost

    关于BOOST,撞车,严重撞车。每一次都让我有点无语。
    第一次是我所谓的宏递归,其实就是一个macro library,有一天就不小心在BOOST的library list上
看到了这个东西。当然,BOOST很牛,别人的这个macro是真的library。但是,我们的需求撞车,我们的
实现手段撞车。于是下定决心下次想要实现个什么东西的时候,先去看看BOOST,可以省掉不少脑力。
    本来就没有做好,何必吃力不讨好?
    第二次,当我写下类似的模板代码时:

    template <typename _Tp>
    
void func( _Tp t );


    我总要花掉几秒钟时间去决策func的参数是用_Tp&还是_Tp,也就是所谓的究竟是按值传送还是按引用
传送。如果按值传送,当_Tp为一个类时,复制的东西过多时,显然效率上过不去。作为func的实现者,良
心上更过不去。后来一想,STL的各种算法里到处都是按值传送,这样做总有它的理由吧?
    但是,这样做就是不够完美。
    于是想起了boost::ref。但是这个时候我并不知道boost::ref是个什么东西。我只是以前在各种地方
看到过这个东西。我还是决定自己实现一个。
    实现一个什么?考虑有:

    template <typename _Tp>
    
void func( _Tp t );


    而我这个时候要传递一个类对象过去CBaseObject obj。为了效率,我写下如下的代码:

    template <typename _Tp>
    
class ref_wrapper
    
{
    
public:
        ref_wrapper( _Tp 
&p ) : _obj( &p ) { }
        
operator _Tp& () return *_obj; }    
    
private:
        _Tp 
*_obj;
    }
;


    然后再使用func时,func( ref_wrapper<CBaseObject>( obj ) );这样,发生复制操作的最多就是这
个ref_wrapper,基本上也就是复制了一个指针,而不会复制整个obj。当然,这里可以写一个模板函数去
简化func的调用,如:

    template <typename _Tp>
    ref_wrapper
<_Tp> ref( _Tp &t )
    
{
        
return ref_wrapper<_Tp>( t );
    }


    这样调用的时候就简单了:func( ref( obj ) );
    其实这就是boost的ref库,按照其官方文档,ref库就是:
    The Ref library is a small library that is useful for passing references to function
templates (algorithms) that would usually take copies of their arguments.

    然后我就懵了。于是我不得不在kl_ref.h里写上check out boost::ref for more information的字眼。

    好,接下来说说第三次。
    第三次我遇到了这样一种需求,我需要一个容器,就像你知道的std::list。但是与std::list甚至STL
中所有容器都不同的是,这个容器里保存的东西具有不同的类型。
    这个时候我想起了tuple。我没有实现过tuple。大致上这个东西的实现原理就是利用类型递归来保存
数据,就像loki的type list。另一方面,tuple的尺寸似乎不能动态增长。
    于是我有了自己撇脚的实现:

 

    class base_type
    
{
        
virtual ~base_type() { }
    }
;
    template 
<typename _Tp>
    
class var_wrapper
    
{
    
public:
        var_wrapper( 
const _Tp &t ) : _t( t )  {}
        
operator _Tp& () return _t; }
    
private:
        _Tp _t;
    }
;   

    
class var_list
    
{
    
public:
        typedef std::vector
<base_type*> TypeList;
    
public:
        
        template 
<typename _Tp>
        
void add( const _Tp &t )
        
{
            var_wrapper
<_Tp> *var = new var_wrapper<_Tp>( t );
            _list.push_back( t );
        }
 

        template 
<typename _Tp>
        _Tp 
&get( size_t index )
        
{
            base_type 
*base = _list.at( index );
            typedef var_wrapper
<_Tp> var_type;
            var_type 
*var = static_cast<var_type*>base );
            
return *var;
        }

    
private:
        TypeList _list;
    }

 

    说白了,我就是利用一个包装类将各种类型包装其中,然后利用基类指针实现统一管理。直白地说,我
对这个组件不满意。让人诟病的是,get接口是类型不安全的。例如:

    int a; 
    CBaseObject obj;
    var_list my_var_list;
    my_var_list.add
<int>( a );
    my_var_list.add
<CBaseObject>( obj );


    取出值的时候:

    int b = my_var_list.get<int>0 );
    CBaseObject cobj 
= my_var_list.get<CBaseObject>1 );


    但是,因为get没有类型检查,即使你:

    CBaseObject cobj = my_var_list.get<CBaseObject>0 );


    也不会出错,编译器不会给予你警告。
    事情到此结束,这个类型不安全的组件只能依靠程序员自己的谨慎去生存。

    然后,又是一个不小心,我在boost里看到了any。boost::any库同boost::ref库一样,是一个tiny
library。几十行的代码一目了然。
    boost::any有一个placeholder基类,有一个template <typename ValueType> holder派生类,然后有
一个提供给外部的any类。看了代码后有一种让我喷血的感觉。其实现原理和我自己的完全一致。
    比较而言,我觉得我的var_list撇脚到了极致。因为我封装了容器,而这显然是没必要的,并且限制
了其使用范围。而boost::any则是仅仅封装了类型。
    数据转换方面,boost::any提供了any_cast和unsafe_any_cast。unsafe_any_cast和我这里用的转换
差不多,也就是我说的类型不安全。而他的any_cast呢?则是用到了typeid,多了次类型检查而已。
    没办法,看来var_list需要被删掉,直接搬boost::any过来吧,同样地check out boost::any for more
information...
    现在看来,boost真的很强大。我感觉再怎么偏门的需求,都能在boost里找到个实现。痛定思痛,决定
把boost doc长期开着。

posted on 2008-10-15 11:23 Kevin Lynx 阅读(4707) 评论(10)  编辑 收藏 引用 所属分类: c/c++

评论

# re: 让人无语的boost 2008-10-15 12:04 Fox

你停太久了……  回复  更多评论   

# re: 让人无语的boost[未登录] 2008-10-15 12:17 chinablueker

没有十全十美的实现、架构亦如此。

抓住关键需求。  回复  更多评论   

# re: 让人无语的boost 2008-10-15 12:42 金庆

用到了才知道boost好。我也在学着应用boost.  回复  更多评论   

# re: 让人无语的boost 2008-10-15 14:06 LOGOS

我是看到boost就贴边走
咱惹不起,还躲得起  回复  更多评论   

# re: 让人无语的boost[未登录] 2008-10-15 18:58 missdeer

我也是,过了之后才发现,boost里有更好的……  回复  更多评论   

# re: 让人无语的boost 2008-10-15 21:16 littlewater

偶记得ANY似乎需要RTTI支持……
递归宏很赞,一直使用着……老实说BOOST的那个偶不用的……  回复  更多评论   

# re: 让人无语的boost[未登录] 2008-10-15 23:45 Kevin Lynx

@littlewater
boost::any用到了typeid,这个东西不开RTTI还是可以工作的,但是对于具有vtable的类,要让typeid工作,就需要开RTTI。
  回复  更多评论   

# re: 让人无语的boost[未登录] 2008-10-17 09:49 bugs

博大精深。  回复  更多评论   

# re: 让人无语的boost 2008-12-27 09:27 littlewater

啊这样子的啊?
谢谢指点^^不过不开RTTI为什么typeid还可以工作呢??

机器挂了,以前的链接都没了,好不容易回来^^
  回复  更多评论   

# re: 让人无语的boost[未登录] 2008-12-28 18:16 Kevin Lynx

:)
不开RTTI,typeid只对静态类型有效了,也就是只对编译器就可以确定的类型有效。
  回复  更多评论   


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