Question

I am working on a library whose functions commonly take a vector type (__v4si, or a vector of 4 signed ints) as a parameter. (Note that so far this has nothing to do with the C++ STL vectortemplate class; this is a more primitive construct used to let the compiler generate vectorized SIMD code.)

In my C code I customarily call a wrapper macro that takes a list of int arguments and initializes a __v4si like so:

#define MakeIndex(dims...) ((__v4si){ dims })

This of course works fine in C++ too, but I would like to take advantage of C++'s more expressive type system to clean up calls to my libraries APIs. For example, where I now write something like:

long idx = IndexDotProduct(MakeIndex(1, 2, 3), MakeIndex(4, 5, 6, 7));

which macro-expands to:

long idx = IndexDotProduct(((__v4si){1, 2, 3}), ((__v4si){4, 5, 6, 7}));

I would like instead to be able to write something along the lines of:

long idx = IndexDotProduct({1, 2, 3}, {4, 5, 6, 7});

So, essentially (I think) I want to define a class that is just syntactic sugar around the primitive __v4si type, but that has an implicit cast operator for the list initializer.

How do I do that in C++ 11?

Solution

Here is a formulation that works for both C and C++ code (now using more verbose names as copied and pasted from my library header files):

typedef struct vMAT_Index {
    __v4si v;
#ifdef __cplusplus
    vMAT_Index(__v4si v) : v(v) { }
    vMAT_Index(int v0 = 0, int v1 = 0, int v2 = 0, int v3 = 0) : v((__v4si){ v0, v1, v2, v3 }) { }
#endif
} vMAT_Index;

#define vMAT_MakeIndex(dims...) ((vMAT_Index){ .v = { dims } })

static inline long
vMAT_Index_dot(vMAT_Index a,
               vMAT_Index b)
{
    __v4si c = a.v * b.v;
    return (long)c[0] + c[1] + c[2] + c[3];
}

In C code you still use the helper macro like this:

long idx = vMAT_Index_dot(vMAT_MakeIndex(1, 2, 3), vMAT_MakeIndex(4, 5, 6, 7));

But now in C++ you can just write:

long idx = vMAT_Index_dot({ 1, 2, 3 }, { 4, 5, 6, 7 });

Thanks to nosid for providing the essential answer!

Was it helpful?

Solution

Use implicit constructors to automatically create a vector object from a brace-initializer list:

struct vector
{
    vector(__v4si v);
    vector(int i0, int i1, int i2, int i3);
};

long IndexDotProduct(vector lhs, vector rhs);

long idx = IndexDotProduct(((__v4si){ 1, 2, 3 }), { 4, 5, 6, 7 });
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top