|
Boost : |
From: Adam Badura (abadura_at_[hidden])
Date: 2005-09-26 04:48:59
I use tamplates to allow user to have on class (class name to be honest,
because templates de facto create many classes) with fixed interface to
manipulate on color data (for example color_rgb, color_cmyk, color_yuv) with
abilyty to have many underlying representations.
You could than wrtie simple function:
template<typename color> vertex<color> get_middle(vertex<color> p1,
vertex<color> p2) {
vertex<color> result;
result.color.red((p1.red()+p2.red())/2);
result.color.red((p1.green()+p2.green())/2);
result.color.red((p1.blue()+p2.blue())/2);
result.point = (p1.point+p2.point)/2;
return result;
}
without carying if RGB used by application will be [unsigned char, unsigned
char, unsigned char], or [float, float, float] or somthing like DirectX
uses, or OpenGL or anything else.
You are just sure what color_rgb gives you and if you don't need to
manipulate on actual representation (and usually beside reading adn writing
data you don't have to as I suppose) you can yous its interface and it will
take care on actual underlying representation.
This as I mentioned in previous post could be done by inheritance and
virtual functions. But this would make this class useles in many cases due
to runtime overhead caused by virtual calls (but has many advantages as i
mentioned). So another way is to have templates (yes, indeed this proves
what you say about polymorphism) which a bit less comfortable in use will
however generate fas code (I hope so... :)).
Adam Badura
"Geoffrey Romer" <geoff.romer_at_[hidden]> wrote in message
news:3017301105092521196e6cef15_at_mail.gmail.com...
> I think you're assuming that when I said "polymorphism", I meant
> "inheritance and virtual functions", but "polymorphism" just means
> having one piece of code operate on different kinds of data. Templates
> are a kind of polymorphism, and that's what I'm referring to.
>
> My question, rephrased, is just "why use templates?" What does this
> templated structure give you that you wouldn't get from just having a
> bunch of unrelated classes (rgb_color, cymk_color, etc.)? How would a
> programmer take advantage of your templated structure?
>
> In other words, can you give an example of how you see this library
> being used, in a way that wouldn't be possible (or easy) without
> templates?
>
>
> On 9/25/05, Adam Badura <abadura_at_[hidden]> wrote:
> > Polymorphism would clearly make difference beetwean color
representation
> > and its model. This difference could be nicely checked at complie time
> > without genereting "tamplate errors" which are usually hard to
understand
> > aspecially when nested or when you are not author of the code in which
error
> > is signaled and would like not even look at this code.
> >
> > If I could use polymorphism (I cannot because of code speed) I would
> > have somethinkg like this.
> >
> > class rgb_representation {
> > public:
> > /*
> > ...
> > */
> > virtual double red() const = 0;
> > virtual void red(double) = 0;
> > virtual double green() const = 0;
> > virtual void green(double) = 0;
> > virtual double blue() const = 0;
> > virtual void blue(double) = 0;
> > /*
> > ...
> > */
> > };
> >
> > class color_rgb {
> > public:
> > color_rgb(rgb_representation& data);
> > /*
> > ...
> > */
> > };
> >
> > Naturally this sollution still has cons (beside speed). For easing
> > dealing with different component types (int, float, ...) templates
probably
> > would be still needed. And this makes it harder to use "color_rgb" in
code
> > like this:
> >
> > color_rgb image_buffer[width][height];
> >
> > But it would be easier to make a "statement" on what does
> > "rgb_representation" need and enforce using only right classes in more
> > pleasent (error messages...) way.
> >
> > And again. Using polymorphism could lead to quite another project.
The
> > model could be actualy implemented in abstract base class, but only
> > functions like "red", "green", "blue" would have to be added by user
> > (naturelly common model would be implemented in lib) this would solve
the
> > "image_buffer" problem and few others in this kind...
> >
> > Adam Badura
> >
> > "Geoffrey Romer" <geoff.romer_at_[hidden]> wrote in message
> > news:301730110509250954e16f7d0_at_mail.gmail.com...
> > > I have a question about this approach: what is the purpose of using
> > > templates? What operations do you see as being performed on colors
> > > polymorphically?
> > >
> > > In other words, the only advantage I see to this templated approach
> > > would be to allow clients to write templated functions/classes which
> > > could operate on arbitrary color types, but I can't think of any
> > > interesting functions that would work with your approach.
> > >
> > > (P.S. sorry if this has been addressed earlier in the thread; I only
> > > just joined the list)
> > >
> > > On 9/25/05, Adam Badura <abadura_at_[hidden]> wrote:
> > > > Actually, to be mor acurate I do something like this:
> > > >
> > > > struct rgb_8888 {
> > > > unsigned char _r : 8;
> > > > unsigned char _g : 8;
> > > > unsigned char _b : 8;
> > > > unsigned char : 8;
> > > > unsigned char red() const {/*...*/}
> > > > void red(unsigned char r) {/*...*/}
> > > > unsigned char green() const {/*...*/}
> > > > void green(unsigned char r) {/*...*/}
> > > > unsigned char blue() const {/*...*/}
> > > > void blue(unsigned char r) {/*...*/}
> > > > unsigned char component(unsigned int index) const {{/*...*/}
> > > > unsigned char& component(unsigned int index) {/*...*/}
> > > > };
> > > >
> > > > template<typename Components> class component_traits {
> > > > public:
> > > > typedef ? component_type;
> > > > static const int components;
> > > > static const int indexes[components];
> > > > static const component_type min[components];
> > > > static const component_type max[components];
> > > > };
> > > >
> > > > and than specialization could look like this:
> > > >
> > > > component_traits<rgb_8888>::component_type === usnigned char
> > > > component_traits<rgb_8888>::min === [0, 0, 0]
> > > > component_traits<rgb_8888>::max === [255, 255, 255]
> > > >
> > > > component_traits<rgb_double>::component_type === double
> > > > component_traits<rgb_8888>::min === [0.0, 0.0, 0.0]
> > > > component_traits<rgb_8888>::max === [1.0, 1.0, 1.0]
> > > >
> > > > and so on...
> > > >
> > > > The base concept is that "color" class (like for example
> > "color_rgb",
> > > > "color_yuv") akes car of color model or color space things, and
> > therefore
> > > > must be a template (polymorphism could be used as well, but code
speed
> > is
> > > > here very important [graphic manipulation!] so I decidet: templates)
> > > > parametrized with "components type". This "component type" takes
care
> > for
> > > > serving color data lika values of channels. "components type" knows
> > exact
> > > > types and palcement in memory.
> > > > So if you want to use your own format in wich all channels have
10
> > bits
> > > > size and all is stored in double word you just write simple
components
> > type:
> > > >
> > > > struct your_rgb {
> > > > unsigned int _r : 10;
> > > > unsigned int _g : 10;
> > > > unsigned int _b : 10;
> > > > unsigned int : 2;
> > > > unsigned int red() const { return _r;}
> > > > void red(unsigned int r) {_r = r;}
> > > > unsigned int green() const {return _g;}
> > > > void green(unsigned int r) {_g = g;}
> > > > unsigned int blue() const {return _b;}
> > > > void blue(unsigned int r) {_b = b;}
> > > > unsigned int component(unsigned int index) const {/*...*/}
> > > > unsigned int& component(unsigned int index) {/*...*/}
> > > > };
> > > >
> > > > component_traits<your_rgb>::component_type === usnigned int
> > > > component_traits<your_rgb>::indexes === [0, 1, 2]
> > > > component_traits<your_rgb>::min === [0, 0, 0]
> > > > component_traits<your_rgb>::max === [2^10, 2^10, 2^10]
> > > >
> > > > in this case writing "component" could be a little difficult however
> > youy
> > > > can be sure taht "color class" will not call your functions with
> > improper
> > > > arguments by it self (actually to speed up code control can be
turned of
> > and
> > > > the user may give wrong arguments, but if someone wants to spoild
> > program he
> > > > will do it anyway). Also you dont have to actualy retrun type
> > > > "component_traits<your_rgb>::component_type" but type that behaves
like
> > it
> > > > were this type.
> > > > (component_traits::indexes is to allow another order of data not
> > only
> > > > RGB but for example also BGR, "color class" always [to ease using]
uses
> > > > index 0 for R, 1 for G and 3 for B, this is problem for "compoinent"
> > > > function, to avoid using "swich" in this function, what would make
its
> > > > execution longer, indexes are staticly mapped, so for BGR this array
> > would
> > > > look like:
> > > >
> > > > component_traits<bgr>::indexes === [2, 1, 0]
> > > >
> > > > and "color class" still uses its indexes, but in calls to components
> > > > "component" maps them (staticly) to right indexes.
> > > > Hope everything is understandable... :)
> > > >
> > > > But now I encountered another problem, which I post in differen
> > message.
> > > >
> > > > Adam Badura
> > > >
> > > > "Rob Stewart" <stewart_at_[hidden]> wrote in message
> > > > news:200509201642.j8KGgYci010670_at_shannonhoon.balstatdev.susq.com...
> > > > > From: "Adam Badura" <abadura_at_[hidden]>
> > > > > >
> > > > > > For now I think taht template representation would be best.
What
> > i
> > > > mean
> > > > > > is for example
> > > > > >
> > > > > > struct rgb_8888 {
> > > > > > unsigned char r : 8;
> > > > > > unsigned char g : 8;
> > > > > > unsigned char b : 8;
> > > > > > unsigned char : 8;
> > > > > > };
> > > > > >
> > > > > > struct yuv_422 {
> > > > > > unsigned char y : 4;
> > > > > > unsigned char u : 2;
> > > > > > unsigned char v : 2;
> > > > > > };
> > > > > >
> > > > > > template<typename Components> class color {
> > > > > > private:
> > > > > > Components mComponents;
> > > > > > };
> > > > >
> > > > > I haven't been following your discussion but this looks suspect.
> > > > >
> > > > > First, you'd need to specialize color for each color structure
> > > > > type so the color member functions know how to do the right
> > > > > thing. That obviates what I think you're trying to do with the
> > > > > template.
> > > > >
> > > > > Second, all code using colors must be either templated on color
> > > > > type or will only work with one type. That is, including the
> > > > > representation in the type (color<yuv_422>) means that functions
> > > > > must be written in terms of color<something> and can't work with
> > > > > color<something_else_entirely>.
> > > > >
> > > > > To fix the former problem, you might consider that the color
> > > > > template can provide higher level functionality from primitives
> > > > > supplied by a policy type. Thus, your Components type would have
> > > > > to provide represention plus primitives.
> > > > >
> > > > > To fix the latter problem, you would need an ABC from which
> > > > > color<T> derives.
> > > > >
> > > > > HTH
> > > > >
> > > > > --
> > > > > Rob Stewart stewart_at_[hidden]
> > > > > Software Engineer http://www.sig.com
> > > > > Susquehanna International Group, LLP using std::disclaimer;
> > > > > _______________________________________________
> > > > > Unsubscribe & other changes:
> > > > http://lists.boost.org/mailman/listinfo.cgi/boost
> > > > >
> > > >
> > > >
> > > >
> > > > _______________________________________________
> > > > Unsubscribe & other changes:
> > http://lists.boost.org/mailman/listinfo.cgi/boost
> > > >
> > >
> > > _______________________________________________
> > > Unsubscribe & other changes:
> > http://lists.boost.org/mailman/listinfo.cgi/boost
> > >
> >
> >
> >
> > _______________________________________________
> > Unsubscribe & other changes:
http://lists.boost.org/mailman/listinfo.cgi/boost
> >
>
> _______________________________________________
> Unsubscribe & other changes:
http://lists.boost.org/mailman/listinfo.cgi/boost
>
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk