我有以下两个工会:
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
我试图实现这一点的次数越多,我就越认为我应该创建两个转换函数而不是使用隐式转换运算符。 不过,我想知道这是否可行。有什么建议吗?
答案 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 */ }