【问题标题】:Template class with different order or variables (Color/Pixel class)具有不同顺序或变量的模板类(颜色/像素类)
【发布时间】:2009-11-11 19:27:36
【问题描述】:

我有两个类模板 Color3_t 和 Color4_t,分别存储 3 和 4 个颜色通道,如下所示:

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

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

这两个模板都有几个用于反转、交换等颜色通道的功能,我得到了另一个继承这些类的专用模板——以防 TYPE 是半浮点数或浮点数而不是整数。

问题在于颜色通道的顺序:红色、绿色和蓝色目前是固定的——这意味着我必须为其他颜色通道顺序(如 BGR、GRB 等)创建一个 Color3_t 类模板版本。 )。如何提供不同颜色顺序的参数 - 很可能指向如下颜色结构。

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;

【问题讨论】:

  • 成员的顺序何时重要?
  • 还有。为什么顺序很重要?
  • 用于访问数组或内存缓冲区中的这些对象(结构) - 从文件加载原始数据后 - 通过名称而不是直接索引 0、1、2 访问它们。我还得到了在不同颜色/像素格式上运行的图像类,并且使用通道名称而不是数字更容易。不同的文件格式使用不同的顺序,例如 BMP 图像使用 RGB,TGA 使用 BGR 更不用说更容易从 ULONG/DWORD 中提取 4 通道颜色值。
  • 如果以Color3_t 访问原始内存不会产生未定义的行为,我会感到惊讶。也就是说,当您验证它在您的平台上执行您想要的操作时,您可能想要采用 Dima 的想法,但是让他的 getX() 函数调用到一个特征类中,传递数组。然后特征类可以确定颜色的顺序。
  • 将数据(无论以何种形式出现)转换为一种相同的内部类型不是更简单吗?我不明白为什么,如果文件使用 RGB 或 BGR,您的内部表示应该使用相同的顺序。

标签: c++ templates


【解决方案1】:

您需要将存储的红色/绿色/蓝色类型向下推送到 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

【讨论】:

  • 似乎这是我的想法,但找不到正确的语法来表达它;)谢谢。
【解决方案2】:

好的,这让我想到了。

我的代码基于这样的想法,即基础非虚拟类按照声明的顺序排列在内存中。我认为这不能保证,但 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_listinherit_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>
{};

我没有尝试编译任何这些,所以它会出现令人尴尬的错误。我已经脸红了。

【讨论】:

  • 我认为上面的Brett 解决方案要简单一些。谢谢。
  • 如果您的工具箱中没有type_listinherit_from,它复杂的。我有它们,所以我只需要第一个代码 sn-p 中的几行。 :)
【解决方案3】:

我猜你不能在编译时用模板做你想做的事。你可能有 在运行时执行此操作。

要获得您想要的效果,您需要执行以下操作:


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

【讨论】:

  • “我猜你不能在编译时用模板做你想做的事。”可以采用您的想法并将这些功能放入特征类中。但问题仍然存在:为什么顺序很重要?
  • 谢谢,但这是我已经拥有的。至于编译时间,我希望模板更易于维护 - 意味着更短,但不以使用这些模板的复杂代码为代价。
  • 不同顺序的原因上面已经解释过了;)
猜你喜欢
  • 1970-01-01
  • 2017-05-10
  • 1970-01-01
  • 2017-02-19
  • 1970-01-01
  • 2013-10-16
  • 2018-11-30
  • 1970-01-01
相关资源
最近更新 更多