Boost logo

Boost :

From: Andy Little (andy_at_[hidden])
Date: 2004-07-05 19:22:33


"Doug Gregor" <dgregor_at_[hidden]> wrote
> On Jul 5, 2004, at 3:00 PM, David Abrahams wrote:
>
> > Joel de Guzman <joel_at_[hidden]> writes:

> >>>> in this directory:
> >>> In Boost CVS there is an implementation of result_of, which would be
> >>> used like this:
> >>> result_of<Op(A, B)>::type
> >>
> >> I think this is the best interface I've seen so far. The
> >> result_of_plus
> >> is just a temporary solution while waiting for Doug's result_of work
> >> which was not available at the time.
> >
> > ...which is just a temporary solution while we wait for decltype?
>
> Absolutely. But it's a solution we can use to make C++98/C++0x portable
> libraries. At least, that's the idea

The key issue for me is not result_of which I am happy with, but rather the
resolution of the Op param above to one common function-object (or set of
function-objects)representing plus, minus etc in context of operators.
std::plus and the others in <functional> are the predecessors for what I'm
talkng about but I think are past their best.

IOW one common interface * for result_type of operators ++ * that all UDTs
and fundamental types can implement. This would for example ease use of UDTs
as value_types in my physical-quantities library.I have had some success for
example with boost::inteval etc, but this has required me writing some
result_of style functors in My style rather than implementing one common
functionality. As another example it would allow use of my
physical-quantities type to be used in arrays and matrices etcetera, without
me having to rewrite interfaces in the style of That particular library.

FWIW Here is my take on it.

    result_of<operator_plus(A,B)>::type // ok pretty interface , but
harder to write traits for. ie first_argument_type for compat with
predecessors

    first_argument<operator_plus(A,B)>::type //?

(Other useful traits for operator... precedence, associativity, commutative,
const char*const symbol (return "+";} etc)

So I am happy with that as one user interface, but then a layer further down
such as binary_operation which is wrapped by the interface.
I have currently implemented it thus:

  template<template <typename> class Op>
    struct operator_{ // just a base class for operator_XX functors

        template<typename> struct result; //for result_of
        template<typename F, typename T, typename U>
        struct result<F(T,U)>
        {
            typedef typename binary_operator<
                T,
                Op,
                U
>::result_type type;
        };
         // further members eg.. operator()(...)'s and possibly static
apply(...)'s

   };

    struct operator_minus : operator_<std::minus>{};
    struct operator_plus : operator_<std::plus>{};
    struct operator_multiplies : operator_<std::multiplies>{};
    struct operator_divides : operator_<std::divides>{};
    struct operator_shift_left : operator_<shift_left>{};
 etc

Rationale
Specialising at the level of operator_plus etc above I have tried. It works
ok in (win) VC7.1 but (djgpp) gcc3.2 chokes on it. (That is the extent of my
technology I'm afraid)
// tried like so...

template<>
struct operator_plus::template result<operator_plus(A,B)>{ //<< gcc
chokes here };

However by also providing the binary_operation layer specialisation can
also be achieved via an alternative route. I also happen to like
binary_operation because it represents the set {binary_operations} rather
than bits and pieces which works better for me at a 'generic' level.

regards
Andy Little


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