#include <iostream>
#include <limits>
#include <type_traits>

using namespace std;

struct vec
{
  double x;
  double y;
  double z;
};

namespace details
{
  template <typename T>
  using subscript_function = double(*)(const T&);

  template <typename T>
  constexpr double X(const T& param) { return param.x; }

  template <typename T>
  constexpr double Y(const T& param) { return param.y; }

  template <typename T>
  constexpr double Z(const T& param) { return param.z; }
}

template <typename T, typename = void>
constexpr details::subscript_function<T> my_temp[] = { &details::X<T>, &details::Y<T> };

template <typename T>
constexpr details::subscript_function<T> my_temp<T, enable_if_t<is_floating_point<decltype(details::X(T()))>::value, T>>[] = { &details::X<T>, &details::Y<T>, &details::Z<T> };


int main() {
  vec foo = { 1.0, 2.0, 3.0 };

  for(const auto i : my_temp<decltype(foo)>) {
    cout << (*i)(foo) << endl;
  }
}