The point is to create uniform struct for vertex and for matrix in c++
Pseudocode:
vector<COUNT, T> {
union {
T data[COUNT];
struct { T x, y, z, w; } // if size is 1 -> only x, if 2 -> only x and y ... etc
struct { T u, v; } // same }
}
template<COUNT, VCOUNT, T>
matrix<COUNT, VCOUNT> : vector<COUNT, vector<VCOUNT, T>> {}
And use like this:
void foo() {
v3f pos(0,1,0);
pos.xy /= pos.z;
m4f transform = {{1,0,0,0},{0,1,0,0},{0,0,1,0},{0,0,0,3.456}}
transform.x.y = transform[3][2];
}
I am too close to make this possible, the only thing I can't reach is initialization of matrix:
v4f v; // v4f typedef of vector<4,float>, m4f is matrix<4,4,float>
v = {0,0,1,0}; //work
m4f mat = {v,v,{},v}; //don't work "excess elements in struct initialization"
m4f mat = {{v,v,{}, v}}; // same
Some implementation details
namespace math::detail
{
template<int SIZE, typename T>
struct vector_base {
T _[SIZE];
};
template<typename T>
struct vector_base<1, T> {
union { T _[1]; T x; };
};
template<typename T>
struct vector_base<2, T> {
union { T _[2]; struct { T x, y; }; struct { T u, v; }; };
};
template<typename T>
struct vector_base<3, T> {
union { T _[3]; struct { T x, y, z; }; };
};
template<typename T>
struct vector_base<4, T> {
union { T _[4]; struct { T x, y, z, w; }; };
};
}
namespace math
{
enum VecI { X, Y, Z, W, U = X, V = Y };
template<int SIZE, typename T>
struct vector : detail::vector_base<SIZE, T>
{
using base = detail::vector_base<SIZE, T>;
vector() = default;
template<typename ... Types,
typename std::enable_if<sizeof...(Types) == SIZE, int>::type = 0>
constexpr vector(Types ... s) : base{static_cast<T>(s)... } {}
// some foos, operator overloading
}
template<int size, int vector_size, typename type>
struct matrix : vector<size, vector<vector_size, type>>
{
// special foos only for matrix
}
}
Vector constructor with parameter pack is not compiling in case of matrix:
error: no matching constructor for initialization of 'vector<3, vector<3, float> >'
return {{{1,0,0}, {0,1,0}, {0,0,1}}};
^~~~~~~~~~~~~~~~~~~~~~~~~~~
/math/vector/base.h:62:15: note: candidate template ignored: requirement 'sizeof...(Types) == 3' was not satisfied [with Types = <>]
constexpr vector(Types ... s) : base{static_cast<T>(s)... } {}
^
Next implementation of matrix at least compile, but need initializing with extra braces {{{},{},{}}
and can't inherit some vector properties:
template<int size, int vector_size, typename type>
struct matrix
{
vector _[size];
// foos
}
I am also tried writing constructors for vector_base
, for matrix
, deduction guides for all of them, nothing works.
How to initialize array of arrays in C++ with automatic deduction (can initialize {5, 0.43, .1f}
without errors of type incompatibilities), without implicitly writing types like in m4f mat = {v4f(0,0,1),v4f(0,1,0), v4f(1,0,0)}
, and without "excess" nested braces {{{}}}?
My compiler is clang:9.0.0
with c++17
, also can use c++2a
, or c++20
when it comes.