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

using namespace std;

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

namespace details
{
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 double (*my_temp[])(const vec&) = { &details::X<T>, &details::Y<T> };

template <typename T>
constexpr double (*my_temp<T, enable_if_t<is_floating_point<decltype(details::X(T()))>::value>>[])(const vec&) = { &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;
  }
}