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 vector
template 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?
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!
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 });