coord: use stricter member variable names

use tags for the core coordinate structures to specify what names should
be used for the data variables (in the data union)
This commit is contained in:
Danny Robson 2015-03-03 04:11:30 +11:00
parent 791b91420f
commit e5d99b3370
5 changed files with 148 additions and 73 deletions

View File

@ -29,8 +29,8 @@
namespace util { namespace util {
/// An RGBA colour POD type. /// An RGBA colour POD type.
template <typename T> template <typename T>
struct colour : public detail::coord<4, T> { struct colour : public detail::coord<4,T,detail::rgba> {
using detail::coord<4,T>::coord; using detail::coord<4,T,detail::rgba>::coord;
static const colour WHITE; static const colour WHITE;
static const colour BLACK; static const colour BLACK;

View File

@ -40,102 +40,180 @@ namespace util {
#pragma GCC diagnostic ignored "-Wgnu" #pragma GCC diagnostic ignored "-Wgnu"
#endif #endif
//---------------------------------------------------------------------
// tags for accessor names
struct rgba { };
struct xyzw { };
struct stpq { };
struct whd { };
template <size_t S, typename T, typename...>
struct coord_base {
T data[S];
};
template <typename T>
struct coord_base<3,T,rgba> {
union {
T data[3];
struct { T r,g,b; };
};
};
template <typename T>
struct coord_base<4,T,rgba> {
union {
T data[4];
struct { T r,g,b,a; };
};
};
template <typename T>
struct coord_base<2,T,xyzw> {
union {
T data[2];
struct { T x,y; };
};
};
template <typename T>
struct coord_base<3,T,xyzw> {
union {
T data[3];
struct { T x,y,z; };
};
};
template <typename T>
struct coord_base<4,T,xyzw> {
union {
T data[4];
struct { T x,y,z,w; };
};
};
template <typename T>
struct coord_base<2,T,xyzw,stpq> {
union {
T data[2];
struct { T x,y; };
struct { T s,t; };
};
};
template <typename T>
struct coord_base<3,T,xyzw,stpq> {
union {
T data[3];
struct { T x,y,z; };
struct { T s,t,p; };
};
};
template <typename T>
struct coord_base<4,T,xyzw,stpq> {
union {
T data[4];
struct { T x,y,z,w; };
struct { T s,t,p,q; };
};
};
template <typename T>
struct coord_base<2,T,whd> {
union {
T data[2];
struct { T w,h; };
};
};
template <typename T>
struct coord_base<3,T,whd> {
union {
T data[3];
struct { T w,h,d; };
};
};
//--------------------------------------------------------------------- //---------------------------------------------------------------------
// coord types are not really intended to have arbitrary dimension, so // coord types are not really intended to have arbitrary dimension, so
// don't add specialisations (or a general case) without a decent // don't add specialisations (or a general case) without a decent
// reason. // reason.
template <size_t S, typename T> template <size_t S, typename T, typename...>
struct coord_data; struct coord_init;
//--------------------------------------------------------------------- ////---------------------------------------------------------------------
template <typename T> template <typename T, typename ...tags>
struct coord_data<1, T> struct coord_init<1,T,tags...> : public coord_base<1,T,tags...>
{ {
coord_data () = default; coord_init () = default;
coord_data (T v0): coord_init (T v0):
data { v0 } coord_base<1,T,tags...> ({v0})
{ ; } { ; }
union {
T data[1];
T x;
};
}; };
//--------------------------------------------------------------------- ////---------------------------------------------------------------------
template <typename T> template <typename T, typename ...tags>
struct coord_data<2,T> struct coord_init<2,T,tags...> : public coord_base<2,T,tags...>
{ {
coord_data () = default; coord_init () = default;
coord_data (T v0, T v1): coord_init (T v0, T v1):
data { v0, v1 } coord_base<2,T,tags...> ({ v0, v1 })
{ ; } { ; }
union {
T data[2];
struct { T x, y; };
struct { T s, t; };
};
}; };
//--------------------------------------------------------------------- ////---------------------------------------------------------------------
template <typename T> template <typename T, typename ...tags>
struct coord_data<3,T> struct coord_init<3,T,tags...> : public coord_base<3,T,tags...>
{ {
coord_data () = default; coord_init () = default;
coord_data (T v0, T v1, T v2): coord_init (T v0, T v1, T v2):
data { v0, v1, v2 } coord_base<3,T,tags...> ({v0, v1, v2})
{ ; } { ; }
union {
T data[3];
struct { T x, y, z; };
struct { T s, t, p; };
struct { T r, g, b; };
};
}; };
//--------------------------------------------------------------------- ////---------------------------------------------------------------------
template <typename T> template <typename T, typename ...tags>
struct coord_data<4,T> struct coord_init<4,T,tags...> : public coord_base<4,T,tags...>
{ {
coord_data () = default; coord_init () = default;
coord_data (T v0, T v1, T v2, T v3): coord_init (T v0, T v1, T v2, T v3):
data { v0, v1, v2, v3 } coord_base<4,T,tags...> ({ v0, v1, v2, v3 })
{ ; } { ; }
union {
T data[4];
struct { T x, y, z, w; };
struct { T s, t, p, q; };
struct { T r, g, b, a; };
};
}; };
//--------------------------------------------------------------------- ////---------------------------------------------------------------------
template <size_t S, typename T> template <size_t S, typename T, typename ...tags>
struct coord : public coord_data<S,T> { struct coord : public coord_init<S,T,tags...> {
static_assert (S > 0, "coord dimensions must be strictly positive"); static_assert (S > 0, "coord dimensions must be strictly positive");
typedef T value_type; typedef T value_type;
static constexpr size_t dimension = S; static constexpr size_t dimension = S;
static constexpr size_t elements = S; static constexpr size_t elements = S;
using coord_data<S,T>::coord_data; using coord_init<S,T,tags...>::coord_init;
coord () = default; coord () = default;
explicit coord (T v) explicit coord (T v)
{ std::fill (std::begin (this->data), std::end (this->data), v); } { std::fill (std::begin (this->data), std::end (this->data), v); }
coord (const coord<S,T> &rhs) = default; coord (const coord<S,T,tags...> &rhs) = default;
coord& operator= (const coord<S,T> &rhs) = default; coord& operator= (const coord<S,T,tags...> &rhs) = default;
T& operator[] (size_t i) { return this->data[i]; } T& operator[] (size_t i) { return this->data[i]; }
T operator[] (size_t i) const { return this->data[i]; } T operator[] (size_t i) const { return this->data[i]; }
@ -148,12 +226,12 @@ namespace util {
}; };
//--------------------------------------------------------------------- ////---------------------------------------------------------------------
// XXX: Unsure whether this should really be defined for arbitrary // XXX: Unsure whether this should really be defined for arbitrary
// types in a semantic sense, but practicality suggestes this is the // types in a semantic sense, but practicality suggestes this is the
// best option; point/vector dot product is too useful. // best option; point/vector dot product is too useful.
template <size_t S, typename T> template <size_t S, typename T, typename ...tag_a, typename ...tag_b>
T dot (const coord<S,T> &a, const coord<S,T> &b) T dot (const coord<S,T,tag_a...> &a, const coord<S,T,tag_b...> &b)
{ {
return std::inner_product (std::begin (a.data), return std::inner_product (std::begin (a.data),
std::end (a.data), std::end (a.data),

View File

@ -31,8 +31,8 @@
namespace util { namespace util {
/// An n-dimensional position in space. /// An n-dimensional position in space.
template <size_t S, typename T> template <size_t S, typename T>
struct point : public detail::coord<S,T> { struct point : public detail::coord<S,T,detail::xyzw> {
using detail::coord<S,T>::coord; using detail::coord<S,T,detail::xyzw>::coord;
// point operators // point operators
template <typename U> typename std::common_type<T,U>::type distance (const point<S,U> &) const; template <typename U> typename std::common_type<T,U>::type distance (const point<S,U> &) const;

View File

@ -5,10 +5,7 @@
int int
main (int, char**) main (int, char**)
{ {
CHECK_EQ (&util::colour4f::WHITE.x, // Simple check for symbol visibility
&util::colour4f::WHITE.r);
CHECK_EQ (util::colour4f::WHITE.x, 1.f);
CHECK_EQ (util::colour4f::WHITE.r, 1.f); CHECK_EQ (util::colour4f::WHITE.r, 1.f);
CHECK_EQ (util::colour4f::WHITE.g, 1.f); CHECK_EQ (util::colour4f::WHITE.g, 1.f);
CHECK_EQ (util::colour4f::WHITE.b, 1.f); CHECK_EQ (util::colour4f::WHITE.b, 1.f);

View File

@ -29,8 +29,8 @@
namespace util { namespace util {
template <size_t S, typename T> template <size_t S, typename T>
struct vector : public detail::coord<S, T> { struct vector : public detail::coord<S,T,detail::xyzw,detail::stpq> {
using detail::coord<S,T>::coord; using detail::coord<S,T,detail::xyzw,detail::stpq>::coord;
// arithmetic operators // arithmetic operators
vector<S,T> operator* (T) const; vector<S,T> operator* (T) const;