boost函数对象的妙用

来源:互联网 发布:python.exe已停止工作 编辑:程序博客网 时间:2024/06/17 08:58

今天在boost中看到了如下的函数用法:


       trim_copy_if(str,is_punct()||is_digit()||is_space()) 作用是将字符串str两端的所有的标点,数字和空格都去掉,这种用法很奇妙,能够把函数或起来,仔细看了一下后台的实现代码,实现的很奇妙,值得记录一下,

       1. is_punct(),is_digit()和is_space() 三个从表面上看是函数,但是实际上他们返回的是structure对象,拿is_digit()查看,其后台实现代码为:

   

         inline detail::is_classifiedF 
        is_space(const std::locale& Loc=std::locale())
        {
            return detail::is_classifiedF(std::ctype_base::space, Loc);
        }


        其返回的是is_classifiedF对象,该对象实际上是一个structure()对象,其定义如下:


         struct is_classifiedF :
        public predicate_facade<is_classifiedF>
        {
                // Boost.ResultOf support
                typedef bool result_type;


                // Constructor from a locale
                is_classifiedF(std::ctype_base::mask Type, std::locale const & Loc = std::locale()) :
                    m_Type(Type), m_Locale(Loc) {}
                // Operation
                template<typename CharT>
                bool operator()( CharT Ch ) const
                {
                    return std::use_facet< std::ctype<CharT> >(m_Locale).is( m_Type, Ch );
                }


                #if defined(__BORLANDC__) && (__BORLANDC__ >= 0x560) && (__BORLANDC__ <= 0x582) && !defined(_USE_OLD_RW_STL)
                    template<>
                    bool operator()( char const Ch ) const
                    {
                        return std::use_facet< std::ctype<char> >(m_Locale).is( m_Type, Ch );
                    }
                #endif


            private:
                std::ctype_base::mask m_Type;
                std::locale m_Locale;
       };

      

      第一步的实现比较容易理解,返回一个structure对象,并在该structure对象中重载了()符号。

       2. 第二步是查看如何将这些函数或起来,实际上就是如何将这三个structure或起来,查看一些||操作符的实现代码,如下:


        template<typename Pred1T, typename Pred2T>
        inline Prefor_<Pred1T, Pred2T>
        operator||( 
            const base<Pred1T>& Pred1, 
            const base<Pred2T>& Pred2 )
        {    
            // Doing the static_cast with the pointer instead of the reference
            // is a workaround for some compilers which have problems with
            // static_cast's of template references, i.e. CW8. /grafik/
            return Prefor_<Pred1T,Pred2T>(
                *static_cast<const Pred1T*>(&Pred1), 
                *static_cast<const Pred2T*>(&Pred2));
        }

         

       从上面的代码中可以看出,该操作将两个is_classifiedF structure或成一个 Prefor_对象那三个函数或起来的步骤是:

      先将is_punct()和is_digit()两个对象或成一个临时的Prefor_对象,接着这个临时的Prefor_对象与is_space()函数再或成一个Prefor_对象。


      3. Prefor_对象也是一个structure,该对象也实现了()操作符,以下是该结构的定义


       template<typename Pref1, typename Pref2>


struct Prefor_:public base<Prefor_<Pref1,Pref2> >
{

Prefor_(Pref1 pref1, Pref2 pref2):m_pref1(pref1),m_pref2(pref2){}


template<typename CharT>
bool operator() (CharT c)
{
return m_pref1(c) || m_pref2(c);
}


Pref1 m_pref1;
Pref2 m_pref2;
};


       在()符号重载中,发现其实际上调用的也是is_classifiedF的()操作符。由于我们是三个函数或在一起的,因此该()操作符中是有一次递归调用的。

      

原创粉丝点击