Boost logo

Boost Users :

Subject: Re: [Boost-users] [proto] Question on grammar and operator overloading
From: Hal Finkel (half_at_[hidden])
Date: 2009-10-06 11:48:38


Eric,

Thank you, I'll use the predicate approach for now. I like the idea of
using an array base because I have a lot of existing C and C++ code
which treats complex numbers as a 2 element array, and accesses the
members using the [] operator. I think this is common in
high-performance scientific codes. I'm afraid doing it another way could
lead to the generation of a large number of conditionals which the
optimizer can't figure out how to eliminate (meaning (idx ? imag() :
real()), I'd have to test this on several platforms), or the
introduction of a lot of casts.

 -Hal

On Tue, 2009-10-06 at 08:56 -0400, Eric Niebler wrote:
> Hal Finkel wrote:
> > Hello,
> >
> > I'm writing a complex number class using boost::proto by extending
> > proto::terminal< boost::array<_, 2> >. I've attached a copy of my
> > current code, which compiles, runs, and (at least with both g++ and icc
> > on my machine) demonstrates a significant speed improvement compared to
> > std::complex.
> >
> > However, there is (at least) one thing which don't work as it should:
> >
> > In the grammar I have to specify lazy_complex< double > instead of
> > lazy_complex< _ >, otherwise the compiler cannot find proto's operator
> > overloads, why?
>
> In your grammar, lazy_complex<_> is equivalent to proto::terminal<
> boost::array< _, 2 > >; that is, they describe the same set of
> expression types. Unfortunately, Proto cannot handle a grammar like
> that. The problem is the "2". Proto can only peer inside template
> instantiations as long as none of the template parameters are non-type
> template parameters.
>
> There are a number of hackish solutions. You could define your own type:
>
> template<typename T, typename Size = mpl::int_<2> >
> struct my_array : boost::array< T, Size::value > {};
>
> and use my_array throughout. Then your grammar becomes proto::terminal<
> boost::array< _, mpl::int_<2> > >, or just proto::terminal<
> boost::array< _, _ > >.
>
> The other alternative is to define a predicate that matches boost::array
> types:
>
> template<typename T>
> struct is_boost_array : mpl::false_ {};
> template<typename T, int I>
> struct is_boost_array<boost::array<T,I> > : mpl::true_ {};
>
> and change your grammar to:
>
> proto::and_<
> proto::terminal<_>,
> proto::if_<is_boost_array<proto::_value>()>
> >
>
> Either way. You could even just use some other terminal type besides
> boost::array. std::complex or std::pair would do.
>
> > Note: This code will not compile under 1.37, but will compile under
> > 1.40, because of some issue in 1.37 which manifests itself as a problem
> > with the overloading of the '<<' operator. I've not tested the releases
> > in between 1.37 and 1.40.
>
> Yes, I've fixed some bugs in this area.
>


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net