tags:

views:

88

answers:

3

I got two class templates Color3_t and Color4_t that store 3 and 4 color channels and look like this:

template <typename TYPE>
struct Color3_t
{
   TYPE Red;
   TYPE Green;
   TYPE Blue;

   void Zero()
   {
      Red = Green = Blue = 0;
   }
   (...)
}

Both templates have several function for inverting, swapping etc. color channels and I got another specialized templates that inherit these classes - in case the TYPE is a half float or float instead of integer.

The problem is that the order of color channels : Red,Green and Blue is currently fixed - which means that I would have to create a version of Color3_t class template for each other order of color channels (like BGR, GRB etc.). How can provide and argument with different color order - most likely that points to a color structure like below.

Color data structures for RGB and BGR color order:

template <typename TYPE>
struct ColorRGB_t
{
   TYPE Red;
   TYPE Green;
   TYPE Blue;
};

template <typename TYPE>
struct ColorBGR_t
{
   TYPE Blue;
   TYPE Green;
   TYPE Red;
};

and something I'd like to have - which is obviously wrong and incorrect but should give an idea what I want to achieve.

template <typename TYPE, class COLORORDER<TYPE>>
struct Color3_t : public COLORORDER<TYPE>
{
   void Zero()
   {
      Red = Green = Blue = 0;
   }
   (...)   
};

I also would like to access each color channel directly:

typedef Color3_t<BYTE,ColorBGR_t<BYTE>> ColorRGB8bpc;
ColorRGB8bpc oColor;
oColor.Red = 0;

instead of:

oColor.SomoObject.Red = 0;
A: 
Dima
"I am guessing you cannot do what you want at compile time with templates." One could take your idea and put those functions into a traits class. But the question remains: Why would the order matter?
sbi
Thanks but this is what I already had. As for compile time, I'd like the templates to be easier to maintain - means shorter but not for the cost of much complex code that use these templates.
mslaf
The reason for different order is explained above;)
mslaf
+1  A: 

You Need to push the type that is stored for red/green/blue down into the Color***_t classes like so:

template <typename TYPE>
struct ColorRGB_t
{
   typedef TYPE value_type;

   value_type Red;
   value_type Green;
   value_type Blue;
};

template <typename TYPE>
struct ColorBGR_t
{
   typedef TYPE value_type;

   value_type Blue;
   value_type Green;
   value_type Red;
};

Then Color3 just take one template parameter that is one of your Color***_t types:

template <typename Order_t>
struct Color3 : public Order_t
{
   typedef typename Order_t::value_type value_type;

   void Zero()
   {
      //static cast zero here to avoid compiler warnings when value_type is a float or double
      Order_t::Red = Order_t::Green = Order_t::Blue = static_cast<value_type>(0);
   }
};

And you declare objects as:

Color3<ColorBGR_t<float> > c1;
Color3<ColorRGB_t<float> > c2;

Does that work for you? It avoids the overhead of indexing into an array at runtime and the Red/Green/Blue members are available directly like c1.Red = 0.0.

Brett Hall
Seems like this is what I had in mind but couldn't find the correct syntax to express it;) Thank you.
mslaf
+1  A: 

OK, so this got me thinking.

My code is based on the idea that base non-virtual classes are laid out in memory in the order they are declared. I don't think this is guaranteed, but IMO it's at least quite common. It also allows you to use your color type for different numbers of colors.

template <typename TYPE> struct R { TYPE Red; };
template <typename TYPE> struct G { TYPE Green; };
template <typename TYPE> struct B { TYPE Blue; };

template <typename Bases>
struct Color : inherit_from<Bases>
{
   // ...
};

typedef Color< generate_color_list<R,G,B>::result_t > ColorRGB_t;
typedef Color< generate_color_list<B,G,R>::result_t > ColorBGR_t;

Now all you need is generate_color_list and that inherit_from.

Given this simple type list definition

struct nil {};

template< typename Head, typename Tail >
struct type_list {
  typedef Head head_type;
  typedef Tail tail_type;
};

here's a not very generalized attempt at a color type list generator:

template< typename T1, typename T2, typename T3 >
struct generate_color_list {
  typedef type_list< T1, 
          type_list< T2, 
          type_list< T3, nil > > > result_t;
};

And this is a shot at the inherit_from:

template< typename List >
struct inherit_from;

template<>
struct inherit_from<nil> {}

template< typename Head, class Tail >
struct inherit_from< type_list<Head,Tail> >
  : public Head
  , public inherit_from<Tail>
{};

I have not tried to compile any of this, so it will have embarrassing errors. I'm blushing already.

sbi
I think the Brett's solution above is a bit simpler. Thank you.
mslaf
It _is_ complicated if you don't have the `type_list` and `inherit_from` in your toolbox anyway. I have them, so all I would need are the few lines in the first code snippet. `:)`
sbi