|
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