From e5d99b3370bcf93109a0c938325d6246c3e2d7ab Mon Sep 17 00:00:00 2001 From: Danny Robson Date: Tue, 3 Mar 2015 04:11:30 +1100 Subject: [PATCH] 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) --- colour.hpp | 4 +- detail/coord.hpp | 204 ++++++++++++++++++++++++++++++++--------------- point.hpp | 4 +- test/colour.cpp | 5 +- vector.hpp | 4 +- 5 files changed, 148 insertions(+), 73 deletions(-) diff --git a/colour.hpp b/colour.hpp index 1c57ee5e..ac6b5ac8 100644 --- a/colour.hpp +++ b/colour.hpp @@ -29,8 +29,8 @@ namespace util { /// An RGBA colour POD type. template - 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; diff --git a/detail/coord.hpp b/detail/coord.hpp index d815fd70..16d78888 100644 --- a/detail/coord.hpp +++ b/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 + struct coord_base { + T data[S]; + }; + + + template + struct coord_base<3,T,rgba> { + union { + T data[3]; + struct { T r,g,b; }; + }; + }; + + template + struct coord_base<4,T,rgba> { + union { + T data[4]; + struct { T r,g,b,a; }; + }; + }; + + + template + struct coord_base<2,T,xyzw> { + union { + T data[2]; + struct { T x,y; }; + }; + }; + + + template + struct coord_base<3,T,xyzw> { + union { + T data[3]; + struct { T x,y,z; }; + }; + }; + + + template + struct coord_base<4,T,xyzw> { + union { + T data[4]; + struct { T x,y,z,w; }; + }; + }; + + + template + struct coord_base<2,T,xyzw,stpq> { + union { + T data[2]; + struct { T x,y; }; + struct { T s,t; }; + }; + }; + + + template + struct coord_base<3,T,xyzw,stpq> { + union { + T data[3]; + struct { T x,y,z; }; + struct { T s,t,p; }; + }; + }; + + + template + struct coord_base<4,T,xyzw,stpq> { + union { + T data[4]; + struct { T x,y,z,w; }; + struct { T s,t,p,q; }; + }; + }; + + + template + struct coord_base<2,T,whd> { + union { + T data[2]; + struct { T w,h; }; + }; + }; + + + template + 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 - struct coord_data; + template + struct coord_init; - //--------------------------------------------------------------------- - template - struct coord_data<1, T> + ////--------------------------------------------------------------------- + template + 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 - struct coord_data<2,T> + ////--------------------------------------------------------------------- + template + 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 - struct coord_data<3,T> + ////--------------------------------------------------------------------- + template + 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 - struct coord_data<4,T> + ////--------------------------------------------------------------------- + template + 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 - struct coord : public coord_data { + ////--------------------------------------------------------------------- + template + struct coord : public coord_init { 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::coord_data; + using coord_init::coord_init; coord () = default; explicit coord (T v) { std::fill (std::begin (this->data), std::end (this->data), v); } - coord (const coord &rhs) = default; - coord& operator= (const coord &rhs) = default; + coord (const coord &rhs) = default; + coord& operator= (const coord &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 - T dot (const coord &a, const coord &b) + template + T dot (const coord &a, const coord &b) { return std::inner_product (std::begin (a.data), std::end (a.data), diff --git a/point.hpp b/point.hpp index b244799a..9f811fd1 100644 --- a/point.hpp +++ b/point.hpp @@ -31,8 +31,8 @@ namespace util { /// An n-dimensional position in space. template - struct point : public detail::coord { - using detail::coord::coord; + struct point : public detail::coord { + using detail::coord::coord; // point operators template typename std::common_type::type distance (const point &) const; diff --git a/test/colour.cpp b/test/colour.cpp index 9204da88..fc026e93 100644 --- a/test/colour.cpp +++ b/test/colour.cpp @@ -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); diff --git a/vector.hpp b/vector.hpp index 6ab0054e..816c4547 100644 --- a/vector.hpp +++ b/vector.hpp @@ -29,8 +29,8 @@ namespace util { template - struct vector : public detail::coord { - using detail::coord::coord; + struct vector : public detail::coord { + using detail::coord::coord; // arithmetic operators vector operator* (T) const;