Класс шаблона с другим порядком или переменными (класс Color / Pixel) - PullRequest
2 голосов
/ 11 ноября 2009

У меня есть два шаблона классов Color3_t и Color4_t, которые хранят 3 и 4 цветовых канала и выглядят так:

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

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

Оба шаблона имеют несколько функций для инвертирования, замены и т. Д. Цветовых каналов, и я получил еще один специализированный шаблон, который наследует эти классы - в случае, если ТИП - это половина числа с плавающей точкой или число с плавающей точкой вместо целого числа.

Проблема в том, что порядок цветовых каналов: красный, зеленый и синий в настоящее время фиксирован - это означает, что мне придется создавать версию шаблона класса Color3_t для каждого другого порядка цветовых каналов (например, BGR, GRB и т. Д.). ). Как можно обеспечить и аргументировать с другим порядком цвета - скорее всего, это указывает на цветовую структуру, как показано ниже.

Цветовые структуры данных для порядка цветов RGB и BGR:

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

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

и что-то, что я хотел бы иметь - что явно неправильно и неправильно, но должно дать представление о том, чего я хочу достичь.

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

Я также хотел бы получить доступ к каждому цветному каналу напрямую:

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

вместо:

oColor.SomoObject.Red = 0;

Ответы [ 3 ]

1 голос
/ 11 ноября 2009

Вам нужно вставить тип, который хранится для красного / зеленого / синего, в классы Color *** _ t следующим образом:

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;
};

Тогда Color3 просто примет один параметр шаблона, который является одним из ваших типов Color *** _ t:

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);
   }
};

И вы объявляете объекты как:

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

Это работает для вас? Это позволяет избежать накладных расходов на индексирование в массив во время выполнения, и элементы Red / Green / Blue доступны напрямую, например c1.Red = 0.0.

1 голос
/ 11 ноября 2009

ОК, это заставило меня задуматься.

Мой код основан на идее, что базовые не виртуальные классы размещаются в памяти в порядке их объявления. Я не думаю, что это гарантировано, но IMO, по крайней мере, довольно распространено. Это также позволяет вам использовать ваш тип цвета для различного количества цветов.

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;

Теперь все, что вам нужно, это generate_color_list и это inherit_from.

Учитывая это определение списка простых типов

struct nil {};

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

Вот не очень обобщенная попытка генератора списка типов цвета:

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

А это выстрел в 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>
{};

Я не пытался скомпилировать ничего из этого, поэтому у него будут смущающие ошибки. Я уже краснею.

0 голосов
/ 11 ноября 2009

Я предполагаю, что вы не можете делать то, что вы хотите во время компиляции с шаблонами. У вас наверное есть сделать это во время выполнения.

Чтобы получить желаемый эффект, вам нужно сделать что-то вроде этого:


template &lt typename TYPE &gt
struct color3channel
{
  TYPE channels[3];

  int rIndex, bIndex, gIndex;

  TYPE getR() const {return channels[rIndex];}
  TYPE getG() const {return channels[gIndex];}
  TYPE getB() const {return channels[bIndex];}
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...