convenient Vector3f classDo the C++ standards guarantee that unused private fields will influence sizeof?Is it a missed optimization, when a compile-time known reference takes space in a non-aggregate struct?When should you use a class vs a struct in C++?How to call a parent class function from derived class function?Meaning of 'const' last in a function declaration of a class?Memory comparison, which is faster?Failed to specialize function templateHow to sort “vector” which contains class objects? And why I am wrong?Accessing a static member function from another classFailure while trying to construct a std::list with an allocatorInconsistent overload resolution for constexpr member functions across compilers

SQL Always On COPY ONLY backups - what's the point if I cant restore the AG from these backups?

Can taking my 1-week-old on a 6-7 hours journey in the car lead to medical complications?

Project Euler Problem 45

Is Sanskrit really the mother of all languages?

How to create large inductors (1H) for audio use?

Phrase request for "work in" in the context of gyms

What's in a druid's grove?

Why would one hemisphere of a planet be very mountainous while the other is flat?

Book where main character comes out of stasis bubble

Entering the US with dual citizenship but US passport is long expired?

In-universe, why does Doc Brown program the time machine to go to 1955?

Golfball Dimples on spaceships (and planes)?

How to calculate the power level of a Commander deck?

Infinitely many primes

How could a planet have one hemisphere way warmer than the other without the planet being tidally locked?

Looking for a big fantasy novel about scholarly monks that sort of worship math?

Are there mathematical concepts that exist in the fourth dimension, but not in the third dimension?

What exactly is Apple Cider

Supervisor wants me to support a diploma-thesis SW tool after I graduated

Global variables and information security

Male viewpoint in an erotic novel

Who's this voice acting performer?

Why are some hotels asking you to book through Booking.com instead of matching the price at the front desk?

I won a car in a poker game. How is that taxed in Canada?



convenient Vector3f class


Do the C++ standards guarantee that unused private fields will influence sizeof?Is it a missed optimization, when a compile-time known reference takes space in a non-aggregate struct?When should you use a class vs a struct in C++?How to call a parent class function from derived class function?Meaning of 'const' last in a function declaration of a class?Memory comparison, which is faster?Failed to specialize function templateHow to sort “vector” which contains class objects? And why I am wrong?Accessing a static member function from another classFailure while trying to construct a std::list with an allocatorInconsistent overload resolution for constexpr member functions across compilers






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;








6















Sometimes there is a need to have a Vector3f class, which has x, y and z members, and can be indexed as a float[3] array at the same time (there are several questions here at SO already about this).



Something like:



struct Vector3f 
float data[3];
float &x = data[0];
float &y = data[1];
float &z = data[2];
;


With this, we can write this:



Vector3f v;
v.x = 2.0f;
v.y = 3.0f;
v.z = 4.0f;
glVertex3fv(v.data);


But this implementation is bad, because references take space in the struct (which is quite unfortunate. I don't see any reason why references cannot be removed in this particular case, maybe it is missed optimization from the compiler's part).



But, with [[no_unique_address]] I had this idea:



#include <new>

template <int INDEX>
class Vector3fProperty
public:
operator float() const
return propertyValue();

float &operator=(float value)
float &v = propertyValue();
v = value;
return v;

private:
float &propertyValue()
return std::launder(reinterpret_cast<float*>(this))[INDEX];

float propertyValue() const
return std::launder(reinterpret_cast<const float*>(this))[INDEX];

;

struct Vector3f
[[no_unique_address]]
Vector3fProperty<0> x;
[[no_unique_address]]
Vector3fProperty<1> y;
[[no_unique_address]]
Vector3fProperty<2> z;

float data[3];
;

static_assert(sizeof(Vector3f)==12);


So, basically, I have properties in the struct, which handles the access to x, y and z. These properties should not take space, as they are empty, and have the attribute of [[no_unique_address]]



What do you think about this approach? Does it have UB?




Note, this question is about a class, for which all these are possible:



Vector3f v;
v.x = 1;
float tmp = v.x;
float *c = v.<something>; // there, c points to a float[3] array









share|improve this question





















  • 2





    @JesperJuhl: and there are cases, where this matters a lot.

    – geza
    8 hours ago






  • 4





    why not have v.data[0], v.data[1], v.data[2] and v.x(), v.y(), v.z()?

    – slepic
    8 hours ago






  • 1





    @JesperJuhl Unhelpful comment is unhelpful. Just because there may be specific applications where tripling the size of your type doesn't matter doesn't mean you shouldn't care at all about the implementation of fundamental library components like this.

    – Barry
    8 hours ago






  • 1





    @slepic: because that's a function call. v.x()=2.0f looks ugly. v.setX(2.0f) is not as terse as it could be.

    – geza
    8 hours ago






  • 4





    In this case, @JesperJuhl, I would personally assume it matters, on the grounds that "array of three floats and not doubles, specifically named x, y, and z" is highly suggestive of 3D graphics. It's thus likely to be used in a context where a large number of Vector3fs must be stored (to represent an object's vertices) and performance is extremely important (because it has to compete with other 3D graphics libraries), and thus essentially storing three pointers would be highly undesirable.

    – Justin Time
    7 hours ago

















6















Sometimes there is a need to have a Vector3f class, which has x, y and z members, and can be indexed as a float[3] array at the same time (there are several questions here at SO already about this).



Something like:



struct Vector3f 
float data[3];
float &x = data[0];
float &y = data[1];
float &z = data[2];
;


With this, we can write this:



Vector3f v;
v.x = 2.0f;
v.y = 3.0f;
v.z = 4.0f;
glVertex3fv(v.data);


But this implementation is bad, because references take space in the struct (which is quite unfortunate. I don't see any reason why references cannot be removed in this particular case, maybe it is missed optimization from the compiler's part).



But, with [[no_unique_address]] I had this idea:



#include <new>

template <int INDEX>
class Vector3fProperty
public:
operator float() const
return propertyValue();

float &operator=(float value)
float &v = propertyValue();
v = value;
return v;

private:
float &propertyValue()
return std::launder(reinterpret_cast<float*>(this))[INDEX];

float propertyValue() const
return std::launder(reinterpret_cast<const float*>(this))[INDEX];

;

struct Vector3f
[[no_unique_address]]
Vector3fProperty<0> x;
[[no_unique_address]]
Vector3fProperty<1> y;
[[no_unique_address]]
Vector3fProperty<2> z;

float data[3];
;

static_assert(sizeof(Vector3f)==12);


So, basically, I have properties in the struct, which handles the access to x, y and z. These properties should not take space, as they are empty, and have the attribute of [[no_unique_address]]



What do you think about this approach? Does it have UB?




Note, this question is about a class, for which all these are possible:



Vector3f v;
v.x = 1;
float tmp = v.x;
float *c = v.<something>; // there, c points to a float[3] array









share|improve this question





















  • 2





    @JesperJuhl: and there are cases, where this matters a lot.

    – geza
    8 hours ago






  • 4





    why not have v.data[0], v.data[1], v.data[2] and v.x(), v.y(), v.z()?

    – slepic
    8 hours ago






  • 1





    @JesperJuhl Unhelpful comment is unhelpful. Just because there may be specific applications where tripling the size of your type doesn't matter doesn't mean you shouldn't care at all about the implementation of fundamental library components like this.

    – Barry
    8 hours ago






  • 1





    @slepic: because that's a function call. v.x()=2.0f looks ugly. v.setX(2.0f) is not as terse as it could be.

    – geza
    8 hours ago






  • 4





    In this case, @JesperJuhl, I would personally assume it matters, on the grounds that "array of three floats and not doubles, specifically named x, y, and z" is highly suggestive of 3D graphics. It's thus likely to be used in a context where a large number of Vector3fs must be stored (to represent an object's vertices) and performance is extremely important (because it has to compete with other 3D graphics libraries), and thus essentially storing three pointers would be highly undesirable.

    – Justin Time
    7 hours ago













6












6








6


2






Sometimes there is a need to have a Vector3f class, which has x, y and z members, and can be indexed as a float[3] array at the same time (there are several questions here at SO already about this).



Something like:



struct Vector3f 
float data[3];
float &x = data[0];
float &y = data[1];
float &z = data[2];
;


With this, we can write this:



Vector3f v;
v.x = 2.0f;
v.y = 3.0f;
v.z = 4.0f;
glVertex3fv(v.data);


But this implementation is bad, because references take space in the struct (which is quite unfortunate. I don't see any reason why references cannot be removed in this particular case, maybe it is missed optimization from the compiler's part).



But, with [[no_unique_address]] I had this idea:



#include <new>

template <int INDEX>
class Vector3fProperty
public:
operator float() const
return propertyValue();

float &operator=(float value)
float &v = propertyValue();
v = value;
return v;

private:
float &propertyValue()
return std::launder(reinterpret_cast<float*>(this))[INDEX];

float propertyValue() const
return std::launder(reinterpret_cast<const float*>(this))[INDEX];

;

struct Vector3f
[[no_unique_address]]
Vector3fProperty<0> x;
[[no_unique_address]]
Vector3fProperty<1> y;
[[no_unique_address]]
Vector3fProperty<2> z;

float data[3];
;

static_assert(sizeof(Vector3f)==12);


So, basically, I have properties in the struct, which handles the access to x, y and z. These properties should not take space, as they are empty, and have the attribute of [[no_unique_address]]



What do you think about this approach? Does it have UB?




Note, this question is about a class, for which all these are possible:



Vector3f v;
v.x = 1;
float tmp = v.x;
float *c = v.<something>; // there, c points to a float[3] array









share|improve this question
















Sometimes there is a need to have a Vector3f class, which has x, y and z members, and can be indexed as a float[3] array at the same time (there are several questions here at SO already about this).



Something like:



struct Vector3f 
float data[3];
float &x = data[0];
float &y = data[1];
float &z = data[2];
;


With this, we can write this:



Vector3f v;
v.x = 2.0f;
v.y = 3.0f;
v.z = 4.0f;
glVertex3fv(v.data);


But this implementation is bad, because references take space in the struct (which is quite unfortunate. I don't see any reason why references cannot be removed in this particular case, maybe it is missed optimization from the compiler's part).



But, with [[no_unique_address]] I had this idea:



#include <new>

template <int INDEX>
class Vector3fProperty
public:
operator float() const
return propertyValue();

float &operator=(float value)
float &v = propertyValue();
v = value;
return v;

private:
float &propertyValue()
return std::launder(reinterpret_cast<float*>(this))[INDEX];

float propertyValue() const
return std::launder(reinterpret_cast<const float*>(this))[INDEX];

;

struct Vector3f
[[no_unique_address]]
Vector3fProperty<0> x;
[[no_unique_address]]
Vector3fProperty<1> y;
[[no_unique_address]]
Vector3fProperty<2> z;

float data[3];
;

static_assert(sizeof(Vector3f)==12);


So, basically, I have properties in the struct, which handles the access to x, y and z. These properties should not take space, as they are empty, and have the attribute of [[no_unique_address]]



What do you think about this approach? Does it have UB?




Note, this question is about a class, for which all these are possible:



Vector3f v;
v.x = 1;
float tmp = v.x;
float *c = v.<something>; // there, c points to a float[3] array






c++ c++20






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited 8 hours ago







geza

















asked 8 hours ago









gezageza

16.2k3 gold badges39 silver badges95 bronze badges




16.2k3 gold badges39 silver badges95 bronze badges










  • 2





    @JesperJuhl: and there are cases, where this matters a lot.

    – geza
    8 hours ago






  • 4





    why not have v.data[0], v.data[1], v.data[2] and v.x(), v.y(), v.z()?

    – slepic
    8 hours ago






  • 1





    @JesperJuhl Unhelpful comment is unhelpful. Just because there may be specific applications where tripling the size of your type doesn't matter doesn't mean you shouldn't care at all about the implementation of fundamental library components like this.

    – Barry
    8 hours ago






  • 1





    @slepic: because that's a function call. v.x()=2.0f looks ugly. v.setX(2.0f) is not as terse as it could be.

    – geza
    8 hours ago






  • 4





    In this case, @JesperJuhl, I would personally assume it matters, on the grounds that "array of three floats and not doubles, specifically named x, y, and z" is highly suggestive of 3D graphics. It's thus likely to be used in a context where a large number of Vector3fs must be stored (to represent an object's vertices) and performance is extremely important (because it has to compete with other 3D graphics libraries), and thus essentially storing three pointers would be highly undesirable.

    – Justin Time
    7 hours ago












  • 2





    @JesperJuhl: and there are cases, where this matters a lot.

    – geza
    8 hours ago






  • 4





    why not have v.data[0], v.data[1], v.data[2] and v.x(), v.y(), v.z()?

    – slepic
    8 hours ago






  • 1





    @JesperJuhl Unhelpful comment is unhelpful. Just because there may be specific applications where tripling the size of your type doesn't matter doesn't mean you shouldn't care at all about the implementation of fundamental library components like this.

    – Barry
    8 hours ago






  • 1





    @slepic: because that's a function call. v.x()=2.0f looks ugly. v.setX(2.0f) is not as terse as it could be.

    – geza
    8 hours ago






  • 4





    In this case, @JesperJuhl, I would personally assume it matters, on the grounds that "array of three floats and not doubles, specifically named x, y, and z" is highly suggestive of 3D graphics. It's thus likely to be used in a context where a large number of Vector3fs must be stored (to represent an object's vertices) and performance is extremely important (because it has to compete with other 3D graphics libraries), and thus essentially storing three pointers would be highly undesirable.

    – Justin Time
    7 hours ago







2




2





@JesperJuhl: and there are cases, where this matters a lot.

– geza
8 hours ago





@JesperJuhl: and there are cases, where this matters a lot.

– geza
8 hours ago




4




4





why not have v.data[0], v.data[1], v.data[2] and v.x(), v.y(), v.z()?

– slepic
8 hours ago





why not have v.data[0], v.data[1], v.data[2] and v.x(), v.y(), v.z()?

– slepic
8 hours ago




1




1





@JesperJuhl Unhelpful comment is unhelpful. Just because there may be specific applications where tripling the size of your type doesn't matter doesn't mean you shouldn't care at all about the implementation of fundamental library components like this.

– Barry
8 hours ago





@JesperJuhl Unhelpful comment is unhelpful. Just because there may be specific applications where tripling the size of your type doesn't matter doesn't mean you shouldn't care at all about the implementation of fundamental library components like this.

– Barry
8 hours ago




1




1





@slepic: because that's a function call. v.x()=2.0f looks ugly. v.setX(2.0f) is not as terse as it could be.

– geza
8 hours ago





@slepic: because that's a function call. v.x()=2.0f looks ugly. v.setX(2.0f) is not as terse as it could be.

– geza
8 hours ago




4




4





In this case, @JesperJuhl, I would personally assume it matters, on the grounds that "array of three floats and not doubles, specifically named x, y, and z" is highly suggestive of 3D graphics. It's thus likely to be used in a context where a large number of Vector3fs must be stored (to represent an object's vertices) and performance is extremely important (because it has to compete with other 3D graphics libraries), and thus essentially storing three pointers would be highly undesirable.

– Justin Time
7 hours ago





In this case, @JesperJuhl, I would personally assume it matters, on the grounds that "array of three floats and not doubles, specifically named x, y, and z" is highly suggestive of 3D graphics. It's thus likely to be used in a context where a large number of Vector3fs must be stored (to represent an object's vertices) and performance is extremely important (because it has to compete with other 3D graphics libraries), and thus essentially storing three pointers would be highly undesirable.

– Justin Time
7 hours ago












5 Answers
5






active

oldest

votes


















3

















But this implementation is bad, because references take space in the struct (which is quite unfortunate. I don't see any reason why references cannot be removed in this particular case, maybe it is missed optimization from the compiler's part).




This looks like a complicated issue. Standard-layout classes have to be compatible between each other. And so compilers are not allowed to eliminate any member, regardless of how they are defined. For non standard-layout? Who knows. For more info read this: Do the C++ standards guarantee that unused private fields will influence sizeof?



From my experience compilers never remove class members, even if they are "unused" (e.g. formally sizeof does use them).




Does it have UB?




I think this is UB. First of all [[no_unique_address]] only means that the member need not have a unique address, not that it must not have a unique address. Secondly it is not clear where your data member starts. Again, compilers are free to use or not paddings of previous [[no_unique_address]] class members. Meaning your accessors may access incorrect piece of memory.



Another problem is that you want to access "outer" memory from the "inner" class. AFAIK such thing is also UB in C++.




What do you think about this approach?




Assuming it is correct (which is not) I still don't like it. You want getters/setters but C++ does not support this feature. So instead of doing those weird, complicated constructs (imagine other people maintaining this code) how about simply do



struct Vector3f 
float data[3];
float x()
return data[0];

void x(float value)
data[0] = value;

...
;


You say this code is ugly. Maybe it is. But it is simple, easy to read and maintain. There's no UB, it does not depend on potential hacks with unions, and does exactly what you want, except for beauty requirement. :)






share|improve this answer



























  • You may be interested, I asked the "remove class member" part here: stackoverflow.com/questions/57811424/…

    – geza
    6 hours ago


















4
















If this is going to live in a header, and you have some confidence in your compiler's optimizing capabilities, you can probably stick to a plain-old operator[]() overload and expect the compiler to be smart enough to elide the call and return the element that you want. E.g.:



class Vec3f 
public:
float x;
float y;
float z;

float &operator[](int i)
if(i == 0)
return x;

if(i == 1)
return y;

if(i == 2)
return z;


;


I tossed this into Compiler Explorer (https://godbolt.org/z/0X4FPL), which showed clang optimizing the operator[] call away at -O2, and GCC at -O3. Less exciting than your approach, but simple and should work under most circumstances.






share|improve this answer




















  • 1





    Well, this will be optimized only when i is known at compile time, right? godbolt.org/z/evVGPZ

    – freakish
    7 hours ago












  • True! What you are getting in your example is definitely less efficient than the optimal. However, in most applications with a fixed-size array, I imagine it would be uncommon for there to be situations where a specific index cannot be known at compile time. Either an index will be supplied as a literal, or there will be loops over [0,2]. This is of course highly application sensitive, so the anonymous structs/unions proposed by @Xirema is probably the best way to go.

    – youngmit
    7 hours ago


















1
















GLM implements this kind of functionality using anonymous structs inside an anonymous union



I can't personally guarantee that this is standard-compliant, but most major compilers (MSVC, GCC, Clang) will support this idiom:



struct Vector3f 
union
struct
float x, y, z;
;
struct
float data[3];
;
;
Vector3f() : Vector3f(0,0,0)
Vector3f(float x, float y, float z) : x(x), y(y), z(z)
;

int main()
Vector3f vec;
vec.x = 14.5;
std::cout << vec.data[0] << std::endl; //Should print 14.5
vec.y = -22.345;
std::cout << vec.data[1] << std::endl; //Should print -22.345
std::cout << sizeof(vec) << std::endl; //On most platforms will print 12



The non-standard behavior is in the anonymous struct used to group the letters together, which GCC will issue a warning about. As far as I know, the union itself should be valid, because the datatypes are all identical, but you should still check with your compiler documentation if you're unsure whether this is valid or not.



As an added convenience, we can also overload the brackets operator to shorten our syntax a little:



struct Vector3f 
/*...*/
float& operator[](size_t index) return data[index];
float operator[](size_t index) const return data[index];
;



int main()
Vector3f vec;
vec.x = 14.5;
std::cout << vec[0] << std::endl; //Should print 14.5
vec.y = -22.345;
std::cout << vec[1] << std::endl; //Should print -22.345
std::cout << sizeof(vec) << std::endl; //On most platforms will print 12




Just for clarity, accessing inactive members in the way I am is valid according to the C++ standard, because those members share a "common subsequence":




If two union members are standard-layout types, it's well-defined to examine their common subsequence on any compiler.



CPP Reference: Union Declaration




Because x and data[0] are



  • Both floats,

  • Both occupy the same memory,

  • Are both standard Layout types as the standard defines them,

It's perfectly valid to access one or the other regardless of which is currently active.






share|improve this answer






















  • 1





    This is UB. C++ (unlike C) does not allow accessing other union members once initialized with one.

    – freakish
    8 hours ago







  • 1





    @freakish It does if (and only if) the types of the inactive union members are the same as the active members and occupy the same memory.

    – Xirema
    8 hours ago











  • @Xirema it is technically UB from a standards perspective. However AFAIK all compilers have chosen to define the behavior for compatibility reasons (within reason). Unless you're thinking that "compatible types" makes this OK...

    – Mgetz
    8 hours ago







  • 3





    it's UB and uses two GNU extensions a) anonymous struct not allowed by ISO . b) union type punning works. Not ALL compilers support that, but GNU collections works in non-strict mode. Xinera misquotes clause, because it relates to stucts with common begin, which isn't the case here.

    – Swift - Friday Pie
    8 hours ago







  • 3





    common sequence doesn't apply here.. it would have applied if both members were standard-layout ctypes with equivalent declarations. Either two arrays or two structs. SO it's technically type punning, because way how array is aligned may be (platform defined) different from struct.. especially if certain pragmas were used in code.

    – Swift - Friday Pie
    8 hours ago



















0
















As stated, this is impossible: pointer arithmetic is defined only within an array, and there’s no way (without putting a reference in the class, which takes up space in current implementations) to have v.x refer to an array element.






share|improve this answer
































    0
















    There's no need for reinterpret_cast, nor unions. You can define a simple operator[]:



    struct Vector3f 
    float x, y, z;
    float& operator[](std::size_t i)return *(&x + i);
    ;


    If you want a strong guarantee that this will work, though, you need to make sure that your class is Standard Layout. In practice, it should work in most cases, even if it's not. For instance, don't add any virtual functions to this class.






    share|improve this answer

























    • Pointer arithmetic cannot be used to move from one member to another, only within arrays.

      – Davis Herring
      3 hours ago













    Your Answer






    StackExchange.ifUsing("editor", function ()
    StackExchange.using("externalEditor", function ()
    StackExchange.using("snippets", function ()
    StackExchange.snippets.init();
    );
    );
    , "code-snippets");

    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "1"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader:
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/4.0/"u003ecc by-sa 4.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    ,
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );














    draft saved

    draft discarded
















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f57810925%2fconvenient-vector3f-class%23new-answer', 'question_page');

    );

    Post as a guest















    Required, but never shown

























    5 Answers
    5






    active

    oldest

    votes








    5 Answers
    5






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    3

















    But this implementation is bad, because references take space in the struct (which is quite unfortunate. I don't see any reason why references cannot be removed in this particular case, maybe it is missed optimization from the compiler's part).




    This looks like a complicated issue. Standard-layout classes have to be compatible between each other. And so compilers are not allowed to eliminate any member, regardless of how they are defined. For non standard-layout? Who knows. For more info read this: Do the C++ standards guarantee that unused private fields will influence sizeof?



    From my experience compilers never remove class members, even if they are "unused" (e.g. formally sizeof does use them).




    Does it have UB?




    I think this is UB. First of all [[no_unique_address]] only means that the member need not have a unique address, not that it must not have a unique address. Secondly it is not clear where your data member starts. Again, compilers are free to use or not paddings of previous [[no_unique_address]] class members. Meaning your accessors may access incorrect piece of memory.



    Another problem is that you want to access "outer" memory from the "inner" class. AFAIK such thing is also UB in C++.




    What do you think about this approach?




    Assuming it is correct (which is not) I still don't like it. You want getters/setters but C++ does not support this feature. So instead of doing those weird, complicated constructs (imagine other people maintaining this code) how about simply do



    struct Vector3f 
    float data[3];
    float x()
    return data[0];

    void x(float value)
    data[0] = value;

    ...
    ;


    You say this code is ugly. Maybe it is. But it is simple, easy to read and maintain. There's no UB, it does not depend on potential hacks with unions, and does exactly what you want, except for beauty requirement. :)






    share|improve this answer



























    • You may be interested, I asked the "remove class member" part here: stackoverflow.com/questions/57811424/…

      – geza
      6 hours ago















    3

















    But this implementation is bad, because references take space in the struct (which is quite unfortunate. I don't see any reason why references cannot be removed in this particular case, maybe it is missed optimization from the compiler's part).




    This looks like a complicated issue. Standard-layout classes have to be compatible between each other. And so compilers are not allowed to eliminate any member, regardless of how they are defined. For non standard-layout? Who knows. For more info read this: Do the C++ standards guarantee that unused private fields will influence sizeof?



    From my experience compilers never remove class members, even if they are "unused" (e.g. formally sizeof does use them).




    Does it have UB?




    I think this is UB. First of all [[no_unique_address]] only means that the member need not have a unique address, not that it must not have a unique address. Secondly it is not clear where your data member starts. Again, compilers are free to use or not paddings of previous [[no_unique_address]] class members. Meaning your accessors may access incorrect piece of memory.



    Another problem is that you want to access "outer" memory from the "inner" class. AFAIK such thing is also UB in C++.




    What do you think about this approach?




    Assuming it is correct (which is not) I still don't like it. You want getters/setters but C++ does not support this feature. So instead of doing those weird, complicated constructs (imagine other people maintaining this code) how about simply do



    struct Vector3f 
    float data[3];
    float x()
    return data[0];

    void x(float value)
    data[0] = value;

    ...
    ;


    You say this code is ugly. Maybe it is. But it is simple, easy to read and maintain. There's no UB, it does not depend on potential hacks with unions, and does exactly what you want, except for beauty requirement. :)






    share|improve this answer



























    • You may be interested, I asked the "remove class member" part here: stackoverflow.com/questions/57811424/…

      – geza
      6 hours ago













    3














    3










    3










    But this implementation is bad, because references take space in the struct (which is quite unfortunate. I don't see any reason why references cannot be removed in this particular case, maybe it is missed optimization from the compiler's part).




    This looks like a complicated issue. Standard-layout classes have to be compatible between each other. And so compilers are not allowed to eliminate any member, regardless of how they are defined. For non standard-layout? Who knows. For more info read this: Do the C++ standards guarantee that unused private fields will influence sizeof?



    From my experience compilers never remove class members, even if they are "unused" (e.g. formally sizeof does use them).




    Does it have UB?




    I think this is UB. First of all [[no_unique_address]] only means that the member need not have a unique address, not that it must not have a unique address. Secondly it is not clear where your data member starts. Again, compilers are free to use or not paddings of previous [[no_unique_address]] class members. Meaning your accessors may access incorrect piece of memory.



    Another problem is that you want to access "outer" memory from the "inner" class. AFAIK such thing is also UB in C++.




    What do you think about this approach?




    Assuming it is correct (which is not) I still don't like it. You want getters/setters but C++ does not support this feature. So instead of doing those weird, complicated constructs (imagine other people maintaining this code) how about simply do



    struct Vector3f 
    float data[3];
    float x()
    return data[0];

    void x(float value)
    data[0] = value;

    ...
    ;


    You say this code is ugly. Maybe it is. But it is simple, easy to read and maintain. There's no UB, it does not depend on potential hacks with unions, and does exactly what you want, except for beauty requirement. :)






    share|improve this answer
















    But this implementation is bad, because references take space in the struct (which is quite unfortunate. I don't see any reason why references cannot be removed in this particular case, maybe it is missed optimization from the compiler's part).




    This looks like a complicated issue. Standard-layout classes have to be compatible between each other. And so compilers are not allowed to eliminate any member, regardless of how they are defined. For non standard-layout? Who knows. For more info read this: Do the C++ standards guarantee that unused private fields will influence sizeof?



    From my experience compilers never remove class members, even if they are "unused" (e.g. formally sizeof does use them).




    Does it have UB?




    I think this is UB. First of all [[no_unique_address]] only means that the member need not have a unique address, not that it must not have a unique address. Secondly it is not clear where your data member starts. Again, compilers are free to use or not paddings of previous [[no_unique_address]] class members. Meaning your accessors may access incorrect piece of memory.



    Another problem is that you want to access "outer" memory from the "inner" class. AFAIK such thing is also UB in C++.




    What do you think about this approach?




    Assuming it is correct (which is not) I still don't like it. You want getters/setters but C++ does not support this feature. So instead of doing those weird, complicated constructs (imagine other people maintaining this code) how about simply do



    struct Vector3f 
    float data[3];
    float x()
    return data[0];

    void x(float value)
    data[0] = value;

    ...
    ;


    You say this code is ugly. Maybe it is. But it is simple, easy to read and maintain. There's no UB, it does not depend on potential hacks with unions, and does exactly what you want, except for beauty requirement. :)







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited 7 hours ago

























    answered 7 hours ago









    freakishfreakish

    41.6k7 gold badges102 silver badges142 bronze badges




    41.6k7 gold badges102 silver badges142 bronze badges















    • You may be interested, I asked the "remove class member" part here: stackoverflow.com/questions/57811424/…

      – geza
      6 hours ago

















    • You may be interested, I asked the "remove class member" part here: stackoverflow.com/questions/57811424/…

      – geza
      6 hours ago
















    You may be interested, I asked the "remove class member" part here: stackoverflow.com/questions/57811424/…

    – geza
    6 hours ago





    You may be interested, I asked the "remove class member" part here: stackoverflow.com/questions/57811424/…

    – geza
    6 hours ago













    4
















    If this is going to live in a header, and you have some confidence in your compiler's optimizing capabilities, you can probably stick to a plain-old operator[]() overload and expect the compiler to be smart enough to elide the call and return the element that you want. E.g.:



    class Vec3f 
    public:
    float x;
    float y;
    float z;

    float &operator[](int i)
    if(i == 0)
    return x;

    if(i == 1)
    return y;

    if(i == 2)
    return z;


    ;


    I tossed this into Compiler Explorer (https://godbolt.org/z/0X4FPL), which showed clang optimizing the operator[] call away at -O2, and GCC at -O3. Less exciting than your approach, but simple and should work under most circumstances.






    share|improve this answer




















    • 1





      Well, this will be optimized only when i is known at compile time, right? godbolt.org/z/evVGPZ

      – freakish
      7 hours ago












    • True! What you are getting in your example is definitely less efficient than the optimal. However, in most applications with a fixed-size array, I imagine it would be uncommon for there to be situations where a specific index cannot be known at compile time. Either an index will be supplied as a literal, or there will be loops over [0,2]. This is of course highly application sensitive, so the anonymous structs/unions proposed by @Xirema is probably the best way to go.

      – youngmit
      7 hours ago















    4
















    If this is going to live in a header, and you have some confidence in your compiler's optimizing capabilities, you can probably stick to a plain-old operator[]() overload and expect the compiler to be smart enough to elide the call and return the element that you want. E.g.:



    class Vec3f 
    public:
    float x;
    float y;
    float z;

    float &operator[](int i)
    if(i == 0)
    return x;

    if(i == 1)
    return y;

    if(i == 2)
    return z;


    ;


    I tossed this into Compiler Explorer (https://godbolt.org/z/0X4FPL), which showed clang optimizing the operator[] call away at -O2, and GCC at -O3. Less exciting than your approach, but simple and should work under most circumstances.






    share|improve this answer




















    • 1





      Well, this will be optimized only when i is known at compile time, right? godbolt.org/z/evVGPZ

      – freakish
      7 hours ago












    • True! What you are getting in your example is definitely less efficient than the optimal. However, in most applications with a fixed-size array, I imagine it would be uncommon for there to be situations where a specific index cannot be known at compile time. Either an index will be supplied as a literal, or there will be loops over [0,2]. This is of course highly application sensitive, so the anonymous structs/unions proposed by @Xirema is probably the best way to go.

      – youngmit
      7 hours ago













    4














    4










    4









    If this is going to live in a header, and you have some confidence in your compiler's optimizing capabilities, you can probably stick to a plain-old operator[]() overload and expect the compiler to be smart enough to elide the call and return the element that you want. E.g.:



    class Vec3f 
    public:
    float x;
    float y;
    float z;

    float &operator[](int i)
    if(i == 0)
    return x;

    if(i == 1)
    return y;

    if(i == 2)
    return z;


    ;


    I tossed this into Compiler Explorer (https://godbolt.org/z/0X4FPL), which showed clang optimizing the operator[] call away at -O2, and GCC at -O3. Less exciting than your approach, but simple and should work under most circumstances.






    share|improve this answer













    If this is going to live in a header, and you have some confidence in your compiler's optimizing capabilities, you can probably stick to a plain-old operator[]() overload and expect the compiler to be smart enough to elide the call and return the element that you want. E.g.:



    class Vec3f 
    public:
    float x;
    float y;
    float z;

    float &operator[](int i)
    if(i == 0)
    return x;

    if(i == 1)
    return y;

    if(i == 2)
    return z;


    ;


    I tossed this into Compiler Explorer (https://godbolt.org/z/0X4FPL), which showed clang optimizing the operator[] call away at -O2, and GCC at -O3. Less exciting than your approach, but simple and should work under most circumstances.







    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered 8 hours ago









    youngmityoungmit

    3943 silver badges11 bronze badges




    3943 silver badges11 bronze badges










    • 1





      Well, this will be optimized only when i is known at compile time, right? godbolt.org/z/evVGPZ

      – freakish
      7 hours ago












    • True! What you are getting in your example is definitely less efficient than the optimal. However, in most applications with a fixed-size array, I imagine it would be uncommon for there to be situations where a specific index cannot be known at compile time. Either an index will be supplied as a literal, or there will be loops over [0,2]. This is of course highly application sensitive, so the anonymous structs/unions proposed by @Xirema is probably the best way to go.

      – youngmit
      7 hours ago












    • 1





      Well, this will be optimized only when i is known at compile time, right? godbolt.org/z/evVGPZ

      – freakish
      7 hours ago












    • True! What you are getting in your example is definitely less efficient than the optimal. However, in most applications with a fixed-size array, I imagine it would be uncommon for there to be situations where a specific index cannot be known at compile time. Either an index will be supplied as a literal, or there will be loops over [0,2]. This is of course highly application sensitive, so the anonymous structs/unions proposed by @Xirema is probably the best way to go.

      – youngmit
      7 hours ago







    1




    1





    Well, this will be optimized only when i is known at compile time, right? godbolt.org/z/evVGPZ

    – freakish
    7 hours ago






    Well, this will be optimized only when i is known at compile time, right? godbolt.org/z/evVGPZ

    – freakish
    7 hours ago














    True! What you are getting in your example is definitely less efficient than the optimal. However, in most applications with a fixed-size array, I imagine it would be uncommon for there to be situations where a specific index cannot be known at compile time. Either an index will be supplied as a literal, or there will be loops over [0,2]. This is of course highly application sensitive, so the anonymous structs/unions proposed by @Xirema is probably the best way to go.

    – youngmit
    7 hours ago





    True! What you are getting in your example is definitely less efficient than the optimal. However, in most applications with a fixed-size array, I imagine it would be uncommon for there to be situations where a specific index cannot be known at compile time. Either an index will be supplied as a literal, or there will be loops over [0,2]. This is of course highly application sensitive, so the anonymous structs/unions proposed by @Xirema is probably the best way to go.

    – youngmit
    7 hours ago











    1
















    GLM implements this kind of functionality using anonymous structs inside an anonymous union



    I can't personally guarantee that this is standard-compliant, but most major compilers (MSVC, GCC, Clang) will support this idiom:



    struct Vector3f 
    union
    struct
    float x, y, z;
    ;
    struct
    float data[3];
    ;
    ;
    Vector3f() : Vector3f(0,0,0)
    Vector3f(float x, float y, float z) : x(x), y(y), z(z)
    ;

    int main()
    Vector3f vec;
    vec.x = 14.5;
    std::cout << vec.data[0] << std::endl; //Should print 14.5
    vec.y = -22.345;
    std::cout << vec.data[1] << std::endl; //Should print -22.345
    std::cout << sizeof(vec) << std::endl; //On most platforms will print 12



    The non-standard behavior is in the anonymous struct used to group the letters together, which GCC will issue a warning about. As far as I know, the union itself should be valid, because the datatypes are all identical, but you should still check with your compiler documentation if you're unsure whether this is valid or not.



    As an added convenience, we can also overload the brackets operator to shorten our syntax a little:



    struct Vector3f 
    /*...*/
    float& operator[](size_t index) return data[index];
    float operator[](size_t index) const return data[index];
    ;



    int main()
    Vector3f vec;
    vec.x = 14.5;
    std::cout << vec[0] << std::endl; //Should print 14.5
    vec.y = -22.345;
    std::cout << vec[1] << std::endl; //Should print -22.345
    std::cout << sizeof(vec) << std::endl; //On most platforms will print 12




    Just for clarity, accessing inactive members in the way I am is valid according to the C++ standard, because those members share a "common subsequence":




    If two union members are standard-layout types, it's well-defined to examine their common subsequence on any compiler.



    CPP Reference: Union Declaration




    Because x and data[0] are



    • Both floats,

    • Both occupy the same memory,

    • Are both standard Layout types as the standard defines them,

    It's perfectly valid to access one or the other regardless of which is currently active.






    share|improve this answer






















    • 1





      This is UB. C++ (unlike C) does not allow accessing other union members once initialized with one.

      – freakish
      8 hours ago







    • 1





      @freakish It does if (and only if) the types of the inactive union members are the same as the active members and occupy the same memory.

      – Xirema
      8 hours ago











    • @Xirema it is technically UB from a standards perspective. However AFAIK all compilers have chosen to define the behavior for compatibility reasons (within reason). Unless you're thinking that "compatible types" makes this OK...

      – Mgetz
      8 hours ago







    • 3





      it's UB and uses two GNU extensions a) anonymous struct not allowed by ISO . b) union type punning works. Not ALL compilers support that, but GNU collections works in non-strict mode. Xinera misquotes clause, because it relates to stucts with common begin, which isn't the case here.

      – Swift - Friday Pie
      8 hours ago







    • 3





      common sequence doesn't apply here.. it would have applied if both members were standard-layout ctypes with equivalent declarations. Either two arrays or two structs. SO it's technically type punning, because way how array is aligned may be (platform defined) different from struct.. especially if certain pragmas were used in code.

      – Swift - Friday Pie
      8 hours ago
















    1
















    GLM implements this kind of functionality using anonymous structs inside an anonymous union



    I can't personally guarantee that this is standard-compliant, but most major compilers (MSVC, GCC, Clang) will support this idiom:



    struct Vector3f 
    union
    struct
    float x, y, z;
    ;
    struct
    float data[3];
    ;
    ;
    Vector3f() : Vector3f(0,0,0)
    Vector3f(float x, float y, float z) : x(x), y(y), z(z)
    ;

    int main()
    Vector3f vec;
    vec.x = 14.5;
    std::cout << vec.data[0] << std::endl; //Should print 14.5
    vec.y = -22.345;
    std::cout << vec.data[1] << std::endl; //Should print -22.345
    std::cout << sizeof(vec) << std::endl; //On most platforms will print 12



    The non-standard behavior is in the anonymous struct used to group the letters together, which GCC will issue a warning about. As far as I know, the union itself should be valid, because the datatypes are all identical, but you should still check with your compiler documentation if you're unsure whether this is valid or not.



    As an added convenience, we can also overload the brackets operator to shorten our syntax a little:



    struct Vector3f 
    /*...*/
    float& operator[](size_t index) return data[index];
    float operator[](size_t index) const return data[index];
    ;



    int main()
    Vector3f vec;
    vec.x = 14.5;
    std::cout << vec[0] << std::endl; //Should print 14.5
    vec.y = -22.345;
    std::cout << vec[1] << std::endl; //Should print -22.345
    std::cout << sizeof(vec) << std::endl; //On most platforms will print 12




    Just for clarity, accessing inactive members in the way I am is valid according to the C++ standard, because those members share a "common subsequence":




    If two union members are standard-layout types, it's well-defined to examine their common subsequence on any compiler.



    CPP Reference: Union Declaration




    Because x and data[0] are



    • Both floats,

    • Both occupy the same memory,

    • Are both standard Layout types as the standard defines them,

    It's perfectly valid to access one or the other regardless of which is currently active.






    share|improve this answer






















    • 1





      This is UB. C++ (unlike C) does not allow accessing other union members once initialized with one.

      – freakish
      8 hours ago







    • 1





      @freakish It does if (and only if) the types of the inactive union members are the same as the active members and occupy the same memory.

      – Xirema
      8 hours ago











    • @Xirema it is technically UB from a standards perspective. However AFAIK all compilers have chosen to define the behavior for compatibility reasons (within reason). Unless you're thinking that "compatible types" makes this OK...

      – Mgetz
      8 hours ago







    • 3





      it's UB and uses two GNU extensions a) anonymous struct not allowed by ISO . b) union type punning works. Not ALL compilers support that, but GNU collections works in non-strict mode. Xinera misquotes clause, because it relates to stucts with common begin, which isn't the case here.

      – Swift - Friday Pie
      8 hours ago







    • 3





      common sequence doesn't apply here.. it would have applied if both members were standard-layout ctypes with equivalent declarations. Either two arrays or two structs. SO it's technically type punning, because way how array is aligned may be (platform defined) different from struct.. especially if certain pragmas were used in code.

      – Swift - Friday Pie
      8 hours ago














    1














    1










    1









    GLM implements this kind of functionality using anonymous structs inside an anonymous union



    I can't personally guarantee that this is standard-compliant, but most major compilers (MSVC, GCC, Clang) will support this idiom:



    struct Vector3f 
    union
    struct
    float x, y, z;
    ;
    struct
    float data[3];
    ;
    ;
    Vector3f() : Vector3f(0,0,0)
    Vector3f(float x, float y, float z) : x(x), y(y), z(z)
    ;

    int main()
    Vector3f vec;
    vec.x = 14.5;
    std::cout << vec.data[0] << std::endl; //Should print 14.5
    vec.y = -22.345;
    std::cout << vec.data[1] << std::endl; //Should print -22.345
    std::cout << sizeof(vec) << std::endl; //On most platforms will print 12



    The non-standard behavior is in the anonymous struct used to group the letters together, which GCC will issue a warning about. As far as I know, the union itself should be valid, because the datatypes are all identical, but you should still check with your compiler documentation if you're unsure whether this is valid or not.



    As an added convenience, we can also overload the brackets operator to shorten our syntax a little:



    struct Vector3f 
    /*...*/
    float& operator[](size_t index) return data[index];
    float operator[](size_t index) const return data[index];
    ;



    int main()
    Vector3f vec;
    vec.x = 14.5;
    std::cout << vec[0] << std::endl; //Should print 14.5
    vec.y = -22.345;
    std::cout << vec[1] << std::endl; //Should print -22.345
    std::cout << sizeof(vec) << std::endl; //On most platforms will print 12




    Just for clarity, accessing inactive members in the way I am is valid according to the C++ standard, because those members share a "common subsequence":




    If two union members are standard-layout types, it's well-defined to examine their common subsequence on any compiler.



    CPP Reference: Union Declaration




    Because x and data[0] are



    • Both floats,

    • Both occupy the same memory,

    • Are both standard Layout types as the standard defines them,

    It's perfectly valid to access one or the other regardless of which is currently active.






    share|improve this answer















    GLM implements this kind of functionality using anonymous structs inside an anonymous union



    I can't personally guarantee that this is standard-compliant, but most major compilers (MSVC, GCC, Clang) will support this idiom:



    struct Vector3f 
    union
    struct
    float x, y, z;
    ;
    struct
    float data[3];
    ;
    ;
    Vector3f() : Vector3f(0,0,0)
    Vector3f(float x, float y, float z) : x(x), y(y), z(z)
    ;

    int main()
    Vector3f vec;
    vec.x = 14.5;
    std::cout << vec.data[0] << std::endl; //Should print 14.5
    vec.y = -22.345;
    std::cout << vec.data[1] << std::endl; //Should print -22.345
    std::cout << sizeof(vec) << std::endl; //On most platforms will print 12



    The non-standard behavior is in the anonymous struct used to group the letters together, which GCC will issue a warning about. As far as I know, the union itself should be valid, because the datatypes are all identical, but you should still check with your compiler documentation if you're unsure whether this is valid or not.



    As an added convenience, we can also overload the brackets operator to shorten our syntax a little:



    struct Vector3f 
    /*...*/
    float& operator[](size_t index) return data[index];
    float operator[](size_t index) const return data[index];
    ;



    int main()
    Vector3f vec;
    vec.x = 14.5;
    std::cout << vec[0] << std::endl; //Should print 14.5
    vec.y = -22.345;
    std::cout << vec[1] << std::endl; //Should print -22.345
    std::cout << sizeof(vec) << std::endl; //On most platforms will print 12




    Just for clarity, accessing inactive members in the way I am is valid according to the C++ standard, because those members share a "common subsequence":




    If two union members are standard-layout types, it's well-defined to examine their common subsequence on any compiler.



    CPP Reference: Union Declaration




    Because x and data[0] are



    • Both floats,

    • Both occupy the same memory,

    • Are both standard Layout types as the standard defines them,

    It's perfectly valid to access one or the other regardless of which is currently active.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited 7 hours ago

























    answered 8 hours ago









    XiremaXirema

    16.2k3 gold badges20 silver badges54 bronze badges




    16.2k3 gold badges20 silver badges54 bronze badges










    • 1





      This is UB. C++ (unlike C) does not allow accessing other union members once initialized with one.

      – freakish
      8 hours ago







    • 1





      @freakish It does if (and only if) the types of the inactive union members are the same as the active members and occupy the same memory.

      – Xirema
      8 hours ago











    • @Xirema it is technically UB from a standards perspective. However AFAIK all compilers have chosen to define the behavior for compatibility reasons (within reason). Unless you're thinking that "compatible types" makes this OK...

      – Mgetz
      8 hours ago







    • 3





      it's UB and uses two GNU extensions a) anonymous struct not allowed by ISO . b) union type punning works. Not ALL compilers support that, but GNU collections works in non-strict mode. Xinera misquotes clause, because it relates to stucts with common begin, which isn't the case here.

      – Swift - Friday Pie
      8 hours ago







    • 3





      common sequence doesn't apply here.. it would have applied if both members were standard-layout ctypes with equivalent declarations. Either two arrays or two structs. SO it's technically type punning, because way how array is aligned may be (platform defined) different from struct.. especially if certain pragmas were used in code.

      – Swift - Friday Pie
      8 hours ago













    • 1





      This is UB. C++ (unlike C) does not allow accessing other union members once initialized with one.

      – freakish
      8 hours ago







    • 1





      @freakish It does if (and only if) the types of the inactive union members are the same as the active members and occupy the same memory.

      – Xirema
      8 hours ago











    • @Xirema it is technically UB from a standards perspective. However AFAIK all compilers have chosen to define the behavior for compatibility reasons (within reason). Unless you're thinking that "compatible types" makes this OK...

      – Mgetz
      8 hours ago







    • 3





      it's UB and uses two GNU extensions a) anonymous struct not allowed by ISO . b) union type punning works. Not ALL compilers support that, but GNU collections works in non-strict mode. Xinera misquotes clause, because it relates to stucts with common begin, which isn't the case here.

      – Swift - Friday Pie
      8 hours ago







    • 3





      common sequence doesn't apply here.. it would have applied if both members were standard-layout ctypes with equivalent declarations. Either two arrays or two structs. SO it's technically type punning, because way how array is aligned may be (platform defined) different from struct.. especially if certain pragmas were used in code.

      – Swift - Friday Pie
      8 hours ago








    1




    1





    This is UB. C++ (unlike C) does not allow accessing other union members once initialized with one.

    – freakish
    8 hours ago






    This is UB. C++ (unlike C) does not allow accessing other union members once initialized with one.

    – freakish
    8 hours ago





    1




    1





    @freakish It does if (and only if) the types of the inactive union members are the same as the active members and occupy the same memory.

    – Xirema
    8 hours ago





    @freakish It does if (and only if) the types of the inactive union members are the same as the active members and occupy the same memory.

    – Xirema
    8 hours ago













    @Xirema it is technically UB from a standards perspective. However AFAIK all compilers have chosen to define the behavior for compatibility reasons (within reason). Unless you're thinking that "compatible types" makes this OK...

    – Mgetz
    8 hours ago






    @Xirema it is technically UB from a standards perspective. However AFAIK all compilers have chosen to define the behavior for compatibility reasons (within reason). Unless you're thinking that "compatible types" makes this OK...

    – Mgetz
    8 hours ago





    3




    3





    it's UB and uses two GNU extensions a) anonymous struct not allowed by ISO . b) union type punning works. Not ALL compilers support that, but GNU collections works in non-strict mode. Xinera misquotes clause, because it relates to stucts with common begin, which isn't the case here.

    – Swift - Friday Pie
    8 hours ago






    it's UB and uses two GNU extensions a) anonymous struct not allowed by ISO . b) union type punning works. Not ALL compilers support that, but GNU collections works in non-strict mode. Xinera misquotes clause, because it relates to stucts with common begin, which isn't the case here.

    – Swift - Friday Pie
    8 hours ago





    3




    3





    common sequence doesn't apply here.. it would have applied if both members were standard-layout ctypes with equivalent declarations. Either two arrays or two structs. SO it's technically type punning, because way how array is aligned may be (platform defined) different from struct.. especially if certain pragmas were used in code.

    – Swift - Friday Pie
    8 hours ago






    common sequence doesn't apply here.. it would have applied if both members were standard-layout ctypes with equivalent declarations. Either two arrays or two structs. SO it's technically type punning, because way how array is aligned may be (platform defined) different from struct.. especially if certain pragmas were used in code.

    – Swift - Friday Pie
    8 hours ago












    0
















    As stated, this is impossible: pointer arithmetic is defined only within an array, and there’s no way (without putting a reference in the class, which takes up space in current implementations) to have v.x refer to an array element.






    share|improve this answer





























      0
















      As stated, this is impossible: pointer arithmetic is defined only within an array, and there’s no way (without putting a reference in the class, which takes up space in current implementations) to have v.x refer to an array element.






      share|improve this answer



























        0














        0










        0









        As stated, this is impossible: pointer arithmetic is defined only within an array, and there’s no way (without putting a reference in the class, which takes up space in current implementations) to have v.x refer to an array element.






        share|improve this answer













        As stated, this is impossible: pointer arithmetic is defined only within an array, and there’s no way (without putting a reference in the class, which takes up space in current implementations) to have v.x refer to an array element.







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered 7 hours ago









        Davis HerringDavis Herring

        12.2k1 gold badge8 silver badges37 bronze badges




        12.2k1 gold badge8 silver badges37 bronze badges
























            0
















            There's no need for reinterpret_cast, nor unions. You can define a simple operator[]:



            struct Vector3f 
            float x, y, z;
            float& operator[](std::size_t i)return *(&x + i);
            ;


            If you want a strong guarantee that this will work, though, you need to make sure that your class is Standard Layout. In practice, it should work in most cases, even if it's not. For instance, don't add any virtual functions to this class.






            share|improve this answer

























            • Pointer arithmetic cannot be used to move from one member to another, only within arrays.

              – Davis Herring
              3 hours ago















            0
















            There's no need for reinterpret_cast, nor unions. You can define a simple operator[]:



            struct Vector3f 
            float x, y, z;
            float& operator[](std::size_t i)return *(&x + i);
            ;


            If you want a strong guarantee that this will work, though, you need to make sure that your class is Standard Layout. In practice, it should work in most cases, even if it's not. For instance, don't add any virtual functions to this class.






            share|improve this answer

























            • Pointer arithmetic cannot be used to move from one member to another, only within arrays.

              – Davis Herring
              3 hours ago













            0














            0










            0









            There's no need for reinterpret_cast, nor unions. You can define a simple operator[]:



            struct Vector3f 
            float x, y, z;
            float& operator[](std::size_t i)return *(&x + i);
            ;


            If you want a strong guarantee that this will work, though, you need to make sure that your class is Standard Layout. In practice, it should work in most cases, even if it's not. For instance, don't add any virtual functions to this class.






            share|improve this answer













            There's no need for reinterpret_cast, nor unions. You can define a simple operator[]:



            struct Vector3f 
            float x, y, z;
            float& operator[](std::size_t i)return *(&x + i);
            ;


            If you want a strong guarantee that this will work, though, you need to make sure that your class is Standard Layout. In practice, it should work in most cases, even if it's not. For instance, don't add any virtual functions to this class.







            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered 6 hours ago









            Cássio RenanCássio Renan

            3,87419 silver badges47 bronze badges




            3,87419 silver badges47 bronze badges















            • Pointer arithmetic cannot be used to move from one member to another, only within arrays.

              – Davis Herring
              3 hours ago

















            • Pointer arithmetic cannot be used to move from one member to another, only within arrays.

              – Davis Herring
              3 hours ago
















            Pointer arithmetic cannot be used to move from one member to another, only within arrays.

            – Davis Herring
            3 hours ago





            Pointer arithmetic cannot be used to move from one member to another, only within arrays.

            – Davis Herring
            3 hours ago


















            draft saved

            draft discarded















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid


            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.

            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f57810925%2fconvenient-vector3f-class%23new-answer', 'question_page');

            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            19. јануар Садржај Догађаји Рођења Смрти Празници и дани сећања Види још Референце Мени за навигацијуу

            Israel Cuprins Etimologie | Istorie | Geografie | Politică | Demografie | Educație | Economie | Cultură | Note explicative | Note bibliografice | Bibliografie | Legături externe | Meniu de navigaresite web oficialfacebooktweeterGoogle+Instagramcanal YouTubeInstagramtextmodificaremodificarewww.technion.ac.ilnew.huji.ac.ilwww.weizmann.ac.ilwww1.biu.ac.ilenglish.tau.ac.ilwww.haifa.ac.ilin.bgu.ac.ilwww.openu.ac.ilwww.ariel.ac.ilCIA FactbookHarta Israelului"Negotiating Jerusalem," Palestine–Israel JournalThe Schizoid Nature of Modern Hebrew: A Slavic Language in Search of a Semitic Past„Arabic in Israel: an official language and a cultural bridge”„Latest Population Statistics for Israel”„Israel Population”„Tables”„Report for Selected Countries and Subjects”Human Development Report 2016: Human Development for Everyone„Distribution of family income - Gini index”The World FactbookJerusalem Law„Israel”„Israel”„Zionist Leaders: David Ben-Gurion 1886–1973”„The status of Jerusalem”„Analysis: Kadima's big plans”„Israel's Hard-Learned Lessons”„The Legacy of Undefined Borders, Tel Aviv Notes No. 40, 5 iunie 2002”„Israel Journal: A Land Without Borders”„Population”„Israel closes decade with population of 7.5 million”Time Series-DataBank„Selected Statistics on Jerusalem Day 2007 (Hebrew)”Golan belongs to Syria, Druze protestGlobal Survey 2006: Middle East Progress Amid Global Gains in FreedomWHO: Life expectancy in Israel among highest in the worldInternational Monetary Fund, World Economic Outlook Database, April 2011: Nominal GDP list of countries. Data for the year 2010.„Israel's accession to the OECD”Popular Opinion„On the Move”Hosea 12:5„Walking the Bible Timeline”„Palestine: History”„Return to Zion”An invention called 'the Jewish people' – Haaretz – Israel NewsoriginalJewish and Non-Jewish Population of Palestine-Israel (1517–2004)ImmigrationJewishvirtuallibrary.orgChapter One: The Heralders of Zionism„The birth of modern Israel: A scrap of paper that changed history”„League of Nations: The Mandate for Palestine, 24 iulie 1922”The Population of Palestine Prior to 1948originalBackground Paper No. 47 (ST/DPI/SER.A/47)History: Foreign DominationTwo Hundred and Seventh Plenary Meeting„Israel (Labor Zionism)”Population, by Religion and Population GroupThe Suez CrisisAdolf EichmannJustice Ministry Reply to Amnesty International Report„The Interregnum”Israel Ministry of Foreign Affairs – The Palestinian National Covenant- July 1968Research on terrorism: trends, achievements & failuresThe Routledge Atlas of the Arab–Israeli conflict: The Complete History of the Struggle and the Efforts to Resolve It"George Habash, Palestinian Terrorism Tactician, Dies at 82."„1973: Arab states attack Israeli forces”Agranat Commission„Has Israel Annexed East Jerusalem?”original„After 4 Years, Intifada Still Smolders”From the End of the Cold War to 2001originalThe Oslo Accords, 1993Israel-PLO Recognition – Exchange of Letters between PM Rabin and Chairman Arafat – Sept 9- 1993Foundation for Middle East PeaceSources of Population Growth: Total Israeli Population and Settler Population, 1991–2003original„Israel marks Rabin assassination”The Wye River Memorandumoriginal„West Bank barrier route disputed, Israeli missile kills 2”"Permanent Ceasefire to Be Based on Creation Of Buffer Zone Free of Armed Personnel Other than UN, Lebanese Forces"„Hezbollah kills 8 soldiers, kidnaps two in offensive on northern border”„Olmert confirms peace talks with Syria”„Battleground Gaza: Israeli ground forces invade the strip”„IDF begins Gaza troop withdrawal, hours after ending 3-week offensive”„THE LAND: Geography and Climate”„Area of districts, sub-districts, natural regions and lakes”„Israel - Geography”„Makhteshim Country”Israel and the Palestinian Territories„Makhtesh Ramon”„The Living Dead Sea”„Temperatures reach record high in Pakistan”„Climate Extremes In Israel”Israel in figures„Deuteronom”„JNF: 240 million trees planted since 1901”„Vegetation of Israel and Neighboring Countries”Environmental Law in Israel„Executive branch”„Israel's election process explained”„The Electoral System in Israel”„Constitution for Israel”„All 120 incoming Knesset members”„Statul ISRAEL”„The Judiciary: The Court System”„Israel's high court unique in region”„Israel and the International Criminal Court: A Legal Battlefield”„Localities and population, by population group, district, sub-district and natural region”„Israel: Districts, Major Cities, Urban Localities & Metropolitan Areas”„Israel-Egypt Relations: Background & Overview of Peace Treaty”„Solana to Haaretz: New Rules of War Needed for Age of Terror”„Israel's Announcement Regarding Settlements”„United Nations Security Council Resolution 497”„Security Council resolution 478 (1980) on the status of Jerusalem”„Arabs will ask U.N. to seek razing of Israeli wall”„Olmert: Willing to trade land for peace”„Mapping Peace between Syria and Israel”„Egypt: Israel must accept the land-for-peace formula”„Israel: Age structure from 2005 to 2015”„Global, regional, and national disability-adjusted life years (DALYs) for 306 diseases and injuries and healthy life expectancy (HALE) for 188 countries, 1990–2013: quantifying the epidemiological transition”10.1016/S0140-6736(15)61340-X„World Health Statistics 2014”„Life expectancy for Israeli men world's 4th highest”„Family Structure and Well-Being Across Israel's Diverse Population”„Fertility among Jewish and Muslim Women in Israel, by Level of Religiosity, 1979-2009”„Israel leaders in birth rate, but poverty major challenge”„Ethnic Groups”„Israel's population: Over 8.5 million”„Israel - Ethnic groups”„Jews, by country of origin and age”„Minority Communities in Israel: Background & Overview”„Israel”„Language in Israel”„Selected Data from the 2011 Social Survey on Mastery of the Hebrew Language and Usage of Languages”„Religions”„5 facts about Israeli Druze, a unique religious and ethnic group”„Israël”Israel Country Study Guide„Haredi city in Negev – blessing or curse?”„New town Harish harbors hopes of being more than another Pleasantville”„List of localities, in alphabetical order”„Muncitorii români, doriți în Israel”„Prietenia româno-israeliană la nevoie se cunoaște”„The Higher Education System in Israel”„Middle East”„Academic Ranking of World Universities 2016”„Israel”„Israel”„Jewish Nobel Prize Winners”„All Nobel Prizes in Literature”„All Nobel Peace Prizes”„All Prizes in Economic Sciences”„All Nobel Prizes in Chemistry”„List of Fields Medallists”„Sakharov Prize”„Țara care și-a sfidat "destinul" și se bate umăr la umăr cu Silicon Valley”„Apple's R&D center in Israel grew to about 800 employees”„Tim Cook: Apple's Herzliya R&D center second-largest in world”„Lecții de economie de la Israel”„Land use”Israel Investment and Business GuideA Country Study: IsraelCentral Bureau of StatisticsFlorin Diaconu, „Kadima: Flexibilitate și pragmatism, dar nici un compromis în chestiuni vitale", în Revista Institutului Diplomatic Român, anul I, numărul I, semestrul I, 2006, pp. 71-72Florin Diaconu, „Likud: Dreapta israeliană constant opusă retrocedării teritoriilor cureite prin luptă în 1967", în Revista Institutului Diplomatic Român, anul I, numărul I, semestrul I, 2006, pp. 73-74MassadaIsraelul a crescut in 50 de ani cât alte state intr-un mileniuIsrael Government PortalIsraelIsraelIsraelmmmmmXX451232cb118646298(data)4027808-634110000 0004 0372 0767n7900328503691455-bb46-37e3-91d2-cb064a35ffcc1003570400564274ge1294033523775214929302638955X146498911146498911

            Smell Mother Skizze Discussion Tachometer Jar Alligator Star 끌다 자세 의문 과학적t Barbaric The round system critiques the connection. Definition: A wind instrument of music in use among the Spaniards Nasty Level 이상 분노 금년 월급 근교 Cloth Owner Permissible Shock Purring Parched Raise 오전 장면 햄 서투르다 The smash instructs the squeamish instrument. Large Nosy Nalpure Chalk Travel Crayon Bite your tongue The Hulk 신호 대사 사과하다 The work boosts the knowledgeable size. Steeplump Level Wooden Shake Teaching Jump 이제 복도 접다 공중전화 부지런하다 Rub Average Ruthless Busyglide Glost oven Didelphia Control A fly on the wall Jaws 지하철 거