两个工会之间的圆形铸造操作员

时间:2016-06-19 18:43:38

标签: c++ struct casting operators

我有以下两个工会:

union rgb_color
{
  struct {
    float red;
    float green;
    float blue;
  };
  float raw[3];
};

union hsv_color
{
  struct {
    float hue;
    float saturation;
    float value;
  };
  float raw[3];
}

我想将operator hsv_color()添加到rgb_color union,将operator rgb_color()添加到hsv_color union。有办法吗?如果我转发声明hsv_color,编译器将抛出以下错误:

error: return type 'union hsv_color' is incomplete

我试图实现这一点的次数越多,我就越认为我应该创建两个转换函数而不是使用隐式转换运算符。 不过,我想知道这是否可行。有什么建议吗?

2 个答案:

答案 0 :(得分:2)

我会建议下面的代码,但你的基本假设是3个浮点数的结构将与3个浮点数的数组完全相同的内存可能是错误的。有结构成员对齐。你需要使用一些" pragma pack"指示。 请阅读here例如

struct hsv_color;

struct rgb_color
{
  union
  {
      struct 
      {
        float red;
        float green;
        float blue;
      }rgb;
      float raw[3];
  };
  operator hsv_color();
 };

struct hsv_color
{
    union
    {
      struct 
      {
        float hue;
        float saturation;
        float value;
      } hsv;
      float raw[3];
    };

    operator rgb_color();
};

rgb_color::operator hsv_color()
{
    hsv_color ret;

    // convert 'this' to hsv_color
    ret.hsv.hue = 0;//todo: perform appropriate calculation here
    ret.hsv.saturation = 0;//todo: perform appropriate calculation here
    ret.hsv.value = 0;//todo: perform appropriate calculation here

    return ret;
}

hsv_color::operator rgb_color ()
{
    rgb_color ret;

    // convert 'this' to rgb_color
    ret.rgb.red = 0;//todo: perform appropriate calculation here
    ret.rgb.green = 0;//todo: perform appropriate calculation here
    ret.rgb.blue = 0;//todo: perform appropriate calculation here

    return ret;
}

答案 1 :(得分:1)

我会避免类型惩罚联盟,因为它在严格的别名规则下变为UB。

我认为你涉及一个数组,因为你需要将这个数组传递给一个API,比如opengl。

在这种情况下,我只需使用数组并提供访问器以语义方式访问r,g,b,h,s和v。

您可以使用前向声明提供必要的转换构造函数:

// forward declare
struct hsv_color;

struct rgb_color
{
  rgb_color(float r, float g, float b)
    : raw { r, g, b }
  {}

  // forward declare
  rgb_color(hsv_color);

  float& r() { return raw[0]; }
  const float& r() const { return raw[0]; }
  float& g() { return raw[1]; }
  const float& g() const { return raw[1]; }
  float& b() { return raw[2]; }
  const float& b() const { return raw[2]; }

  const float* data() const  { return raw; }
  float* data()  { return raw; }

  private:
  float raw[3];
};

struct hsv_color
{
  hsv_color(float h, float s, float v)
   : raw { h, s, v }
  {}

  hsv_color(rgb_color rgb) { /*conversion here*/ }

  // more accessors here

  float raw[3];
};

// define

rgb_color::rgb_color(hsv_color hsv) { /* implement here */ }