すっかり忘れていたが今までのパターンではdouble型にしか対応していなかった。
#pragma once ////////////////////////////////////////////////////// ////////////////////////////////////////////////////// // プライマリテンプレート template<typename T> struct GETTER; ////////////////////////////////////////////////////// ////////////////////////////////////////////////////// // 特殊化用の構造体 //小文字 x,y,z用特殊化用の構造体 template<typename T> struct access_xyz { using scalar_t = decltype(T::x); static inline scalar_t& X(T& v) { return v.x; } static inline scalar_t& Y(T& v) { return v.y; } static inline scalar_t& Z(T& v) { return v.z; } static inline const scalar_t& X(const T& v) { return v.x; } static inline const scalar_t& Y(const T& v) { return v.y; } static inline const scalar_t& Z(const T& v) { return v.z; } }; //大文字 X,Y,Z用特殊化用の構造体 template<typename T> struct access_XYZ { using scalar_t = decltype(T::X); static inline scalar_t& X(T& v) { return v.X; } static inline scalar_t& Y(T& v) { return v.Y; } static inline scalar_t& Z(T& v) { return v.Z; } static inline const scalar_t& X(const T& v) { return v.X; } static inline const scalar_t& Y(const T& v) { return v.Y; } static inline const scalar_t& Z(const T& v) { return v.Z; } }; //配列用特殊化用の構造体 template<typename U,typename T> struct access_ARRAY{ static inline U& X(T& v) { return v[0]; } static inline U& Y(T& v) { return v[1]; } static inline U& Z(T& v) { return v[2]; } static inline const U& X(const T& v) { return v[0]; } static inline const U& Y(const T& v) { return v[1]; } static inline const U& Z(const T& v) { return v[2]; } }; ////////////////////////////////////////////////////// ////////////////////////////////////////////////////// // データ型(サンプル) // 型1 struct vec_t { double x, y, z; }; // 型2 struct VEC_t { double X, Y, Z; }; ////////////////////////////////////////////////////// ////////////////////////////////////////////////////// //特殊化1(デフォルトの型) template<> struct GETTER<vec_t> :public access_xyz<vec_t> {}; template<> struct GETTER<VEC_t> :public access_XYZ<VEC_t> {}; ////////////////////////////////////////////////////// ////////////////////////////////////////////////////// // 特殊化2(ポインタ版) template<typename T> struct GETTER<T*> : public access_ARRAY<T,T*> {}; template<class T, std::size_t N> struct GETTER<T[N]> : public access_ARRAY<T, T[N]> {}; template<typename T, std::size_t N> struct GETTER<std::array<T, N> > : public access_ARRAY<T, std::array<T, N> > {}; ////////////////////////////////////////////////////// ////////////////////////////////////////////////////// // 関数本体 template< typename T, class G = GETTER<T> > double length(const T & v) { return sqrt( G::X(v) * G::X(v) + G::Y(v) * G::Y(v) + G::Z(v) * G::Z(v) ); } template< typename T, class G = GETTER<T> > void normalize(T & v) { double L = length(v); G::X(v) = G::X(v) / L; G::Y(v) = G::Y(v) / L; G::Z(v) = G::Z(v) / L; }