
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.