Boost logo

Boost :

From: Steven Watanabe (steven_at_[hidden])
Date: 2007-10-09 11:32:11


AMDG

Simonson, Lucanus J <lucanus.j.simonson <at> intel.com> writes:

> If you have a legacy prism type CPrism and it is conceptually a
> rectangle with the additional z axis data you can pass it into an API I
> have defined that expected a rectangle:
> apiExpectingRectangle(RectangleConcept<CPrism>::mimic(myCPrism));
> Or you can pass it into an API expecting a prism:
> apiExpectingPrism (RectangularPrismConcept<CPrism>::mimic(myCPrism));
> Or you can pass it into an API that is overloaded to expect either a
> rectangle or a prism:
> apiExpectingRectangleOrPrism(RectangleConcept<CPrism>::mimic(myCPrism));
> apiExpectingRectangleOrPrism(RectangularPrismConcept<CPrism>::mimic(myCP
> rism));
> and get different behaviors out of that api depending on which type you
> told it to model the data as.

Suppose that I want to write

template<class Rectangle, class T>
void move_up(Rectangle&, T offset);

to modify a rectangle in place.
if I need to copy the rectangle this isn't
going to work.

The alternative is to have some set of metafunctions/traits/free functions
that allow one to operate directly on the object.

template<class T>
struct is_rectangle : boost::mpl::false_ {}; // default is not a rectangle

template<class T>
struct rectangle_get_x;

template<>
struct rectangle_get_x<CRect> {
    typedef unsigned short result_type;
    result_type operator()(const CRect& rect) const;
};

// etc.

Now generic functions can operate directly on a CRect
without making any copies.

Then, apiExpectingRectangleOrPrism can be declared as

template<class T>
typename boost::enable_if<is_rectangle<T> >::type
apiExpectingRectangleOrPrism(const T&);

template<class T>
typename boost::enable_if<is_prism<T> >::type
apiExpectingRectangleOrPrism(const T&);

If the type passed to this function is either a rectangle or
a prism but not both the call is unambiguous. If the type
that you want to pass in is both then you can disambiguate
by creating an adapter.

template<class T>
struct rectangle_adapter {
    T impl;
};

Alternately, and probably better, you can define
the real functions using different names and have the
generic api forward.

template<class T>
void apiExpectingPrism(const T&);

template<class T>
typename boost::enable_if<is_prism<T> >::type
apiExpectingRectangleOrPrism(const T& t) {
    return(apiExpectingPrism(t));
}

// similarly for rectangle

In Christ,
Steven Watanabe


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