Templated Point class of any dimension I needed to make a point class for a term project that involved arbitrary dimensional points.  I came up with this, and I know that it works fine, but I'm looking to improve it so I can reuse it in the future.  Any criticisms or suggestions are very much appreciated.

#ifndef POINT_HPP
#define POINT_HPP

#include &lt;array&gt;
#include &lt;cmath&gt;
#include &lt;initializer_list&gt;
#include &lt;iostream&gt;

template &lt;size_t D&gt;
struct Point;

template &lt;size_t D&gt;
struct Point {
  Point(const std::initializer_list&lt;double&gt;&amp; v) {
    size_t i = 0;
    for (auto e : v) {
      coordinates_[i++] = e;
    }
  }

  explicit Point(const std::array&lt;double, D&gt;&amp; arr) : coordinates_{arr} {}

  double operator[](size_t dimension) const { return coordinates_[dimension]; }
  Point&lt;D&gt;&amp; operator=(const Point&amp; other) {
    this-&gt;coordinates_ = other.coordinates_;
    return *this;
  }
  std::array&lt;double, D&gt; coordinates_;
};

/*
 * Finds euclidian distance between two Point classes of same dimension
 */
template &lt;size_t D&gt;
double distance(const Point&lt;D&gt;&amp; lhs, const Point&lt;D&gt;&amp; rhs) {
  double dist = 0;
  for (size_t i = 0; i &lt; D; i++) dist += std::pow(lhs[i] - rhs[i], 2);
  return std::sqrt(dist);
}

/*
 * Finds euclidian distance between Point and axis
 */
template &lt;size_t D&gt;
double distance(const Point&lt;D&gt;&amp; point, double value, int axis) {
  return std::abs(point[axis] - value);
}

/*
 * Print the point components of a Point in ascending order.
 * Prints in the form {x, y, z} with no newline.
 */
template &lt;size_t D&gt;
std::ostream&amp; operator&lt;&lt;(std::ostream&amp; os, const Point&lt;D&gt;&amp; point) {
  os &lt;&lt; "{";
  for (size_t i = 0; i &lt; D - 1; i++) {
    os &lt;&lt; point[i] &lt;&lt; ", ";
  }
  os &lt;&lt; point[D - 1] &lt;&lt; "}";
  return os;
}

template &lt;size_t D&gt;
bool operator==(const Point&lt;D&gt;&amp; lhs, const Point&lt;D&gt;&amp; rhs) {
  return lhs.coordinates_ == rhs.coordinates_;
}

namespace std {
/*
 * Make our Point class hashable
 */
template &lt;size_t D&gt;
struct hash&lt;Point&lt;D&gt;&gt; {
  size_t operator()(const Point&lt;D&gt;&amp; x) const {
    return hash&lt;array&lt;double, D&gt;&gt;()(x.coordinates_);
  }
};

/*
 * Also make it swappable for sorting
 */
template &lt;size_t D&gt;
void swap(Point&lt;D&gt;&amp; lhs, Point&lt;D&gt;&amp; rhs) {
  swap(lhs.coordinates_, rhs.coordinates_);
}
}  // namespace std

#endif  // POINT_HPP
Overall, this seems to be a small but useful template.  However, there are a few things that I think might be improved.

Sorting requires more than swap

While the provided swap function would assist in some kind of sorting, without a comparison operator, we still can't actually sort.  This may well be by design, in which case a comment in the code pointing this out would be helpful.

Consider default constructor

There is no simple way at the moment to create a generic templated origin point (all coordinates zero).  This makes it a bit more difficult to create something like a distance_from_origin function that is generic.

Consider projection operator

It's often useful to project, say, a 3D point onto a 2D canvas.  This could also likely be made generic.

Do a range check

The distance function that measures from an axis does no range checking on the axis number and there does not seem to be a good generic way to add one.  Consider providing a range checking version.