Boost logo

Boost :

Subject: Re: [boost] A design for geometric objects
From: Bruno Lalande (bruno.lalande_at_[hidden])
Date: 2008-11-14 16:18:18


> Now you have way to state "X can be viewed as an ellipse". But how would
> you state "if X can be viewed as a circle, then it can be viewed as an
> ellipse (in the way that ellipse_traits<X>::get_width() returns
> circle_traits<X>::get_radius()"?

This comes to say: if circle_traits is specialized for X, then
ellipse_traits is specialized for X. And to forward the right
functions in ellipse_traits<X> to the right ones in circle_traits<X>.

enable_if can help doing that. Unfortunately I don't know if it's
possible to know at compile-time if a specialization exists. But we
can use a trick. I think I got to achieve what you're asking for:

// the primary ellipse_traits

template <class X, class Enable = void>
struct ellipse_traits
{};

// the primary circle_traits

template <class X>
struct circle_traits
{
        // at this stage it's not specialized...
        typedef mpl::false_ specialized;
};

// the following means litterally: " if circle_traits is specialized for X,
// then ellipse_traits<X> exists and it's width() is defined in terms of the
// circle's radius"

template <class X>
struct ellipse_traits<
           X,
           typename enable_if<typename circle_traits<X>::specialized>::type
>
{
   static void width()
   { circle_traits<X>::radius(); }
};

// an ellipse class
struct ellipse;

// an ellipse has its own ellipse_traits, let's define them

template <>
struct ellipse_traits<ellipse>
{
        static void width()
        { cout << "ellipse width" << endl; }
};

// a circle class
struct circle;

// circle_traits of a circle

template <>
struct circle_traits<circle>
{
        static void radius()
        { cout << "circle radius" << endl; }

        // now it's specialized
        typedef mpl::true_ specialized;
};

int main(int, char** argv)
{
        ellipse_traits<ellipse>::width();
        ellipse_traits<circle>::width();
        return 0;
}

The output is:

ellipse width
circle radius

The "specialized" typedef is a bit weird, as it forces the user to
sort of say "yes, I've really specialized it". But the goal is reached
I think: I have never explicitly specialized ellipse_traits<circle>. I
have only said that if circle_traits<X> exists then ellipse_traits<X>
exists and ellipse_traits<X>::width() is circle_traits<X>::radius(),
except if a better specialization of ellipse_traits<X> exists. And the
compiler correctly understood what I meant when I asked for
ellipse_traits<circle>::width().

Does anybody know a way to know if a specialization exists without
using this kind of trick?

Bruno


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