|
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