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:
parent
791b91420f
commit
e5d99b3370
@ -29,8 +29,8 @@
|
||||
namespace util {
|
||||
/// An RGBA colour POD type.
|
||||
template <typename T>
|
||||
struct colour : public detail::coord<4, T> {
|
||||
using detail::coord<4,T>::coord;
|
||||
struct colour : public detail::coord<4,T,detail::rgba> {
|
||||
using detail::coord<4,T,detail::rgba>::coord;
|
||||
|
||||
static const colour WHITE;
|
||||
static const colour BLACK;
|
||||
|
204
detail/coord.hpp
204
detail/coord.hpp
@ -40,102 +40,180 @@ namespace util {
|
||||
#pragma GCC diagnostic ignored "-Wgnu"
|
||||
#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
|
||||
// don't add specialisations (or a general case) without a decent
|
||||
// reason.
|
||||
template <size_t S, typename T>
|
||||
struct coord_data;
|
||||
template <size_t S, typename T, typename...>
|
||||
struct coord_init;
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
template <typename T>
|
||||
struct coord_data<1, T>
|
||||
////---------------------------------------------------------------------
|
||||
template <typename T, typename ...tags>
|
||||
struct coord_init<1,T,tags...> : public coord_base<1,T,tags...>
|
||||
{
|
||||
coord_data () = default;
|
||||
coord_data (T v0):
|
||||
data { v0 }
|
||||
coord_init () = default;
|
||||
coord_init (T v0):
|
||||
coord_base<1,T,tags...> ({v0})
|
||||
{ ; }
|
||||
|
||||
union {
|
||||
T data[1];
|
||||
T x;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
template <typename T>
|
||||
struct coord_data<2,T>
|
||||
////---------------------------------------------------------------------
|
||||
template <typename T, typename ...tags>
|
||||
struct coord_init<2,T,tags...> : public coord_base<2,T,tags...>
|
||||
{
|
||||
coord_data () = default;
|
||||
coord_data (T v0, T v1):
|
||||
data { v0, v1 }
|
||||
coord_init () = default;
|
||||
coord_init (T v0, T v1):
|
||||
coord_base<2,T,tags...> ({ v0, v1 })
|
||||
{ ; }
|
||||
|
||||
union {
|
||||
T data[2];
|
||||
|
||||
struct { T x, y; };
|
||||
struct { T s, t; };
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
template <typename T>
|
||||
struct coord_data<3,T>
|
||||
////---------------------------------------------------------------------
|
||||
template <typename T, typename ...tags>
|
||||
struct coord_init<3,T,tags...> : public coord_base<3,T,tags...>
|
||||
{
|
||||
coord_data () = default;
|
||||
coord_data (T v0, T v1, T v2):
|
||||
data { v0, v1, v2 }
|
||||
coord_init () = default;
|
||||
coord_init (T v0, T v1, T 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>
|
||||
struct coord_data<4,T>
|
||||
////---------------------------------------------------------------------
|
||||
template <typename T, typename ...tags>
|
||||
struct coord_init<4,T,tags...> : public coord_base<4,T,tags...>
|
||||
{
|
||||
coord_data () = default;
|
||||
coord_data (T v0, T v1, T v2, T v3):
|
||||
data { v0, v1, v2, v3 }
|
||||
coord_init () = default;
|
||||
coord_init (T v0, T v1, T v2, T 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>
|
||||
struct coord : public coord_data<S,T> {
|
||||
////---------------------------------------------------------------------
|
||||
template <size_t S, typename T, typename ...tags>
|
||||
struct coord : public coord_init<S,T,tags...> {
|
||||
static_assert (S > 0, "coord dimensions must be strictly positive");
|
||||
|
||||
typedef T value_type;
|
||||
static constexpr size_t dimension = S;
|
||||
static constexpr size_t elements = S;
|
||||
|
||||
using coord_data<S,T>::coord_data;
|
||||
using coord_init<S,T,tags...>::coord_init;
|
||||
coord () = default;
|
||||
|
||||
explicit coord (T v)
|
||||
{ std::fill (std::begin (this->data), std::end (this->data), v); }
|
||||
|
||||
coord (const coord<S,T> &rhs) = default;
|
||||
coord& operator= (const coord<S,T> &rhs) = default;
|
||||
coord (const coord<S,T,tags...> &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) const { return this->data[i]; }
|
||||
@ -148,12 +226,12 @@ namespace util {
|
||||
};
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
////---------------------------------------------------------------------
|
||||
// XXX: Unsure whether this should really be defined for arbitrary
|
||||
// types in a semantic sense, but practicality suggestes this is the
|
||||
// best option; point/vector dot product is too useful.
|
||||
template <size_t S, typename T>
|
||||
T dot (const coord<S,T> &a, const coord<S,T> &b)
|
||||
template <size_t S, typename T, typename ...tag_a, typename ...tag_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),
|
||||
std::end (a.data),
|
||||
|
@ -31,8 +31,8 @@
|
||||
namespace util {
|
||||
/// An n-dimensional position in space.
|
||||
template <size_t S, typename T>
|
||||
struct point : public detail::coord<S,T> {
|
||||
using detail::coord<S,T>::coord;
|
||||
struct point : public detail::coord<S,T,detail::xyzw> {
|
||||
using detail::coord<S,T,detail::xyzw>::coord;
|
||||
|
||||
// point operators
|
||||
template <typename U> typename std::common_type<T,U>::type distance (const point<S,U> &) const;
|
||||
|
@ -5,10 +5,7 @@
|
||||
int
|
||||
main (int, char**)
|
||||
{
|
||||
CHECK_EQ (&util::colour4f::WHITE.x,
|
||||
&util::colour4f::WHITE.r);
|
||||
|
||||
CHECK_EQ (util::colour4f::WHITE.x, 1.f);
|
||||
// Simple check for symbol visibility
|
||||
CHECK_EQ (util::colour4f::WHITE.r, 1.f);
|
||||
CHECK_EQ (util::colour4f::WHITE.g, 1.f);
|
||||
CHECK_EQ (util::colour4f::WHITE.b, 1.f);
|
||||
|
@ -29,8 +29,8 @@
|
||||
|
||||
namespace util {
|
||||
template <size_t S, typename T>
|
||||
struct vector : public detail::coord<S, T> {
|
||||
using detail::coord<S,T>::coord;
|
||||
struct vector : public detail::coord<S,T,detail::xyzw,detail::stpq> {
|
||||
using detail::coord<S,T,detail::xyzw,detail::stpq>::coord;
|
||||
|
||||
// arithmetic operators
|
||||
vector<S,T> operator* (T) const;
|
||||
|
Loading…
Reference in New Issue
Block a user