Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 7436695
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 29, 20262026-05-29T10:16:51+00:00 2026-05-29T10:16:51+00:00

Using the GLSL syntax in C++ I wrote custom vector classes such as vec2

  • 0

Using the GLSL syntax in C++

I wrote custom vector classes such as vec2, vec3 etc. that mimic the GLSL types and look roughly like this:

struct vec3
{
    inline vec3(float x, float y, float z)
      : x(x), y(y), z(z) {}
    union { float x, r, s; };
    union { float y, g, t; };
    union { float z, b, p; };
};

Operations on vectors are implemented this way:

inline vec3 operator +(vec3 a, vec3 b)
{
    return vec3(a.x + b.x, a.y + b.y, a.z + b.z);
}

This allows me to create vectors and access their components using a GLSL-like syntax and perform operations on them almost as if they were numeric types. The unions allow me to refer to the first coordinate indifferently as x or as r, as is the case in GLSL. For instance:

vec3 point = vec3(1.f, 2.f, 3.f);
vec3 other = point + point;
point.x = other.b;

The problem of swizzling

But GLSL also allows swizzled access, even with holes between components. For instance p.yx behaves like a vec2 with p’s x and y swapped. When no component is repeated, it is also an lvalue. Some examples:

other = point.xyy; /* Note: xyy, not xyz */
other.xz = point.xz;
point.xy = other.xx + vec2(1.0f, 2.0f);

Now this could be done using standard getters and setters such as vec2 xy() and void xy(vec2 val). This is what the GLM library does.

Transparent getter and setter

However, I devised this pattern that lets me do exactly the same in C++. Since everything is a POD-struct, I can add more unions:

template<int I, int J> struct MagicVec2
{
    friend struct vec2;
    inline vec2 operator =(vec2 that);

private:
    float ptr[1 + (I > J ? I : J)];
};

template<int I, int J>
inline vec2 MagicVec2<I, J>::operator =(vec2 that)
{
    ptr[I] = that.x; ptr[J] = that.y;
    return *this;
}

And eg. the vec3 class becomes (I simplified things a bit, for instance nothing prevents xx from being used as an lvalue here):

struct vec3
{
    inline vec3(float x, float y, float z)
      : x(x), y(y), z(z) {}

    template<int I, int J, int K>
    inline vec3(MagicVec3<I, J, K> const &v)
      : x(v.ptr[I]), y(v.ptr[J]), z(v.ptr[K]) {}

    union
    {
        struct { float x, y, z; };
        struct { float r, g, b; };
        struct { float s, t, p; };

        MagicVec2<0,0> xx, rr, ss;
        MagicVec2<0,1> xy, rg, st;
        MagicVec2<0,2> xz, rb, sp;
        MagicVec2<1,0> yx, gr, ts;
        MagicVec2<1,1> yy, gg, tt;
        MagicVec2<1,2> yz, gb, tp;
        MagicVec2<2,0> zx, br, ps;
        MagicVec2<2,1> zy, bg, pt;
        MagicVec2<2,2> zz, bb, pp;
        /* Also MagicVec3 and MagicVec4, of course */
    };
};

Basically: I use a union to mix the vector’s floating-point components with a magic object which is not really a vec2 but can be cast implicitly to a vec2 (because there’s a vec2 constructor allowing it), and can be assigned a vec2 (because of its overloaded assignment operator).

I am very satisfied with the result. The GLSL code above works and I believe I get decent type safety. And I can #include a GLSL shader in my C++ code.

Limitations

Of course there are limitations. I know of the following ones:

  • sizeof(point.xz) will be 3*sizeof(float) instead of the expected 2*sizeof(float). This is by design and I do not know whether this could be problematic.
  • &foo.xz cannot be used as a vec2*. This should be OK because I only ever pass these objects by value.

So my question is: what may I have overlooked that will make my life difficult with this pattern? Also, I have not found this pattern anywhere else yet, so if anyone knows its name I am interested.

Note: I wish to stick to C++98, but I do rely on the compiler allowing type-punning through unions. My reason for not wanting C++11 yet is the lack of compiler support on several of my target platforms; all the compilers that are of interest to me support type punning, though.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-29T10:16:52+00:00Added an answer on May 29, 2026 at 10:16 am

    In short: I think that it is difficult to make sure that this pattern works – that’s why you are asking. Moreover, this pattern could be replaced by a standard proxy pattern, for which correctness is easier to guarantee. I have to admit though that the storage overhead of a proxy-based solution is a problem when the proxies are created statically.

    Correctness of the above code

    This is code where there is no obvious bug; but paraphrasing C. A. R. Hoare, this is not code where there is obviously no bug. Moreover, how hard is it to convince oneself that there is no bug?
    I do not see any reason why the pattern would not work – but it is not so easy to prove (even informally) that it will work. In fact, trying doing a proof could fail and point out to some problems.
    To be safe, I would disable all implicitly-generated constructors/assignment operators for MagicVecN classes, just to avoid considering all the associated complications (see subsection below); however doing that is forbidden, because for union members one cannot override the implicitly defined copy assignment operator, as explained by the standard draft I have and by GCC’s error message:

    member ‘MagicVec2<0, 0> vec3::<anonymous union>::xx’ with copy assignment operator not allowed in union
    

    In the attached gist, I instead provide an implementation manually to be safe.

    Note that MagicVec2’s assignment operator should accepts its parameter by const reference (see example below, where this works); implicit conversions still happen (the const reference will point to the created temporary; this would not work without the const qualifier).

    Almost problems, but not quite

    I thought a found a bug (which I didn’t), but it is still somewhat interesting to consider – just to see how many cases must be covered to rule out potential bugs. Would p.xz = p.zx produce the correct results? I thought that MagicVec2‘s implicit assignment operator would be invoked, leading to incorrect results; in fact, it isn’t (I believe) because I and J are different and part of the type. What when the type is the same?
    p.xx = q.rr is safe, but p.xx = p.rr is tricky (even though it might be stupid, but it should still not corrupt memory): is the implicitly-generated assignment operator memcpy-based? The answer seems to be no, but if yes, this would be a memcpy between overlapping memory intervals, which is undefined behavior.

    UPDATE: An actual problem

    As noticed by the OP, the default copy assignment operator is also invoked for the expression p.xz = q.xz; in that case, it will in fact also copy the .y member. As mentioned above, the copy assignment operator cannot be disabled or modified for datatypes which are part of an union.

    The proxy pattern

    Moreover, I believe that there is a much simpler solution, namely the proxy pattern (which you are partially using). MagicVecX should contain a pointer to the containing class instead of ptr; this way you need no trick using unions.

    template<int I, int J> struct MagicVec2
    {
        friend struct vec2;
        inline MagicVec2(vec2* _this): ptr(_this) {}
        inline vec2 operator=(const vec2& that);
    private:
        float *ptr;
    };
    

    I tested this by compiling (but not linking) this code, which sketches the proposed solution: https://gist.github.com/1775054. Note that the code is not complete nor tested – one should also override the copy constructor of MagicVecX.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

Let's say I am using a custom GLSL shader that uses a special interleaved
Using ASP.NET MVC there are situations (such as form submission) that may require a
I have an OpenGL-program using GLSL, that I can run just fine with the
Specifying the GLSL version gives a syntax error when using LWJGL. I haven't tried
Is it possible to set the color of a single vertex using a GLSL
i am using this code to check if my glsl shader compiled fine. glGetObjectParameterivARB(obj,
Using TortoiseSVN against VisualSVN I delete a source file that I should not have
I'm running into a rather strange GLSL compilation error while using Intel HD Graphics
I'm trying to figure out how to do texture mapping using GLSL version 4.10.
So on my program, I draw 2D rectangle using GLSL shader. The rectangle is

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.