Boost logo

Boost :

Subject: Re: [boost] [mpl] is there a or_seq like logical metafunction?
From: Larry Evans (cppljevans_at_[hidden])
Date: 2009-02-16 12:10:33


On 02/15/09 17:50, Steven Watanabe wrote:
> AMDG
>
> Larry Evans wrote:
>> So, in summary, the and_ifops::if_ test has been replaced
>> with the and_iter specialization of <End, End>, and
>> the laziness is achieved by use of and_; however,
>> why not just use eval_if to achieve the laziness:
>
> Because, in theory, mpl::and_ should be just as efficient.
>
>> #include <boost/mpl/eval_if.hpp>
>> <snip>
>> This shaved off a few instantiations (128 vs. 163 on my machine).
>
> Watch out. My tool includes non templates in the instantiation
> count. The total number of instantiations reported depends on
> the #includes. To get a good comparison, you need to subtract
> off the number of instantiations caused by just the #includes.
> (You could look at the call graph, but it's unreliable still).

Good call. I surrounded the call to and_seq with and #ifndef X
and ran with X #def'ed and #undef'ed. Hmm... Got same number of
instantiations. OOPS, the code within the #ifndef ... #endif was:

         typedef
       and_seq<all_true_seq_max>
     and_seq_true_max_meta
     ;

when it should have also included:

         typedef
       and_seq_true_max_meta::type
     and_seq_true_max_type
     ;

That made a huge difference in number of instantiations.

With that change:

implementation profile includes difference
-------------- ------- -------- ----------
and_iter 469 152 317
eval_if_iter 465 149 316
while_if_then 510 149 361

The similarity of and_iter and eval_if_iter surprised me because and_
uses several templates from aux_ and I thought they would have added
significantly to the count.

The while_if_then was an attempt to use a while which was as close as
possible to and_iter; yet, still used something like a c while
statement. I've seen semantics of while expressed in a recursive
equations such as:

   while ~ if b then c;while else skip.

which is pretty close to the way the while_ and the while_if_then are
defined.

The while_if_then template is:

       template
       < class State//nullary metafunction returning current state.
       , template<class>class If//unary bool_ metafunction
       , template<class>class Then//unary metafunction
>
     struct while_if_then
     : eval_if
       < typename If<typename State::type>::type
       , while_if_then
         < Then<typename State::type>
         , If
         , Then
>
       , State
>
     {
     };

Then and_seq using this method was:

     template<class IterNow, class IterEnd>
     struct and_if
     : boost::mpl::deref<IterNow>
     {
     };

     template<class IterEnd>
     struct and_if<IterEnd,IterEnd>
     : boost::mpl::false_
     {
     };

     template<class IterNow, class IterEnd>
     struct and_result
     : boost::mpl::false_
     {
     };

     template<class IterEnd>
     struct and_result<IterEnd,IterEnd>
     : boost::mpl::true_
     {
     };

     template <typename Seq>
     struct and_seq
       {
               typedef typename
             boost::mpl::end<Seq>::type
           end_seq
           ;
             template<class IterNow>
           struct if_
           : and_if<IterNow,end_seq>
           {};
               typedef typename
             boost::mpl::while_if_then
             < typename boost::mpl::begin<Seq>
             , if_
             , boost::mpl::next
>::type
           end_state
           ;
               typedef
             and_result
             < end_seq
             , end_state
>
           type
           ;

       };

[snip]

> This doesn't work because __TIMIING_RULE__ affect bjam level targets,
> but seq_while-time is the name of a Boost.Build main target.
>
> Try:
>
> obj and_seq_while.o : and_seq_while.cpp ;
> time and_seq_while.time : and_seq_while.o ;

Worked great. Thanks Steven!

The times for all three implementations were all the same:

   user: [and_seq_and_iter.o] 0.000016
   system: [and_seq_and_iter.o] 0.000003

And this is where the vector size was BOOST_MPL_LIMIT_VECTOR_SIZE,
which was 20.


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk