2016-06-19 1 views
0

У меня есть следующие два союзов:Круговые операторы приведения между двумя союзами

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_colorunion и operator rgb_color() к hsv_colorunion. Есть ли способ сделать это? Если я вперед объявить hsv_color, компилятор выдает следующее сообщение об ошибке:

error: return type 'union hsv_color' is incomplete 

Чем больше я пытаюсь осуществить это, тем больше я думаю, я должен просто создать две функции для преобразования вместо того, чтобы использовать неявное приведение операторы. Тем не менее, я хотел бы знать, возможно ли это. Какие-либо предложения?

+2

Я надеюсь, что вы не делаете тип-Пунин с этими союзами: например, запись в 'raw', а затем чтение из' оттенка 'и наоборот - UB –

+0

@Revolver_Ocelot: Если UB вы имеете в виду неопределенное поведение, то, черт возьми, этого не знали! Это только на C++ или также в C? – xx77aBs

+1

Вот как работают профсоюзы, если вам нужны «сырые» и «оттенки» в одно и то же время, возможно, это не должно быть объединением в первую очередь. – user463035818

ответ

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

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

Я предполагаю, что вы задействуете массив, потому что вам нужно передать этот массив в API, например opengl.

В этом случае я просто использовал бы массив и предоставил бы аксессурам доступ к семантически доступным г, 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 */ }