スポンサーリンク

色々な型に対応できる関数を作る(5)double型以外に対応する

すっかり忘れていたが今までのパターンでは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;

}

コメントを残す

メールアドレスが公開されることはありません。

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)


この記事のトラックバックURL: