I was writing some geometry-related code again and had a closer look at my function supposed to compute the Euclidean distance between two points (N-dimensional points by the way, hence the N template parameter). Here is a simplified version:template<std::size_t N, typename T>auto distance(const Point<N, T>& lhs, const Point<N, T>& rhs)    -> T{    T res{};    for (std::size_t i = 0 ; i < N ; ++i)    {        auto tmp = std::abs(lhs[i] - rhs[i]);        res += tmp * tmp;    }    return std::sqrt(res);}So far, so good. However, one very common operation is to compare the distances. Generally speaking, when comparing the distances, the sqrt is optimized away and the sum of the squares is compared instead of the distance itself. Therefore, I tried to create some kind of expression template to represent the distance between two points, so that users will benefit from both the ease of use and the get rid of sqrt optimization when comparing distances. Basically, the call of sqrt is not done until the exact value of the distance is needed. Here is the class:template<typename T>struct DistanceExpression{    explicit constexpr DistanceExpression(T data):        _data(data)    {}    operator T() const    {        return std::sqrt(_data);    }    bool operator==(const DistanceExpression& other) const    {        return _data == other._data;    }    bool operator!=(const DistanceExpression& other) const    {        return !(*this == other);    }private:    T _data;};My new distance function is implemented as such:template<std::size_t N, typename T>auto distance(const Point<N, T>& lhs, const Point<N, T>& rhs)    -> DistanceExpression<T>{    T res{};    for (std::size_t i = 0 ; i < N ; ++i)    {        auto tmp = std::abs(lhs[i] - rhs[i]);        res += tmp * tmp;    }    return DistanceExpression<T>{res};}Here is a minimal working code at Coliru. Is such a design reasonable or is it overkill to elegantly solve this problem?
Expression template to compute the Euclidean distance
c++;c++11;mathematics;template
I find all this an overkill. Agreeing in general with Michael Urman, the programmer/user should be aware of such choices. I can clearly see at least two different functions here:template<std::size_t N, typename T>T squared_distance(const Point<N, T>& lhs, const Point<N, T>& rhs){    T res{};    for (std::size_t i = 0 ; i < N ; ++i)    {        auto tmp = lhs[i] - rhs[i];        res += tmp * tmp;    }    return res;}template<std::size_t N, typename T>T distance(const Point<N, T>& lhs, const Point<N, T>& rhs){    return std::sqrt(squared_distance(lhs, rhs));}There are so many more useful cases for introducing expression templates, so why an extra burden for the compiler just for this?For instance, given Point's x, y, vector subtractionz = x - ycould be an expression template, so that z[i] == x[i] - y[i] for each i. Squaring each element would be another expression template, so thatz = square(x - y)would have z[i] == w * w for each i, where w = (x - y)[i]. Then,squared_norm(x - y)would compute the actual reduction astemplate<typename X>T sum(const X& x) { return std::accumulate(x.begin(), x.end(), X{}); }template<typename X>T squared_norm(const X& x) { return sum(square(x)); }assuming Point or a more general expression template are equipped with begin(), end() (which they should). Note I am not using std::inner_product to avoid the extra cost when x is a (lazy) expression template. Then, squared_distance would be trivialtemplate<typename X, typename Y>T squared_distance(const X& x, const Y& y) { return squared_norm(x - y); }or not needed at all, while distance generalized astemplate<typename X, typename Y>T distance(const X& x, const Y& y) { return std::sqrt(squared_distance(x, y)); }There's more to be generalized by considering rvalue references and forwading as appropriate, but I wanted to keep this clean.The user should explicitly use squared Euclidean norms and distances when needed. For instance, consider this scientific article on nearest-neighbor search:In (1), the distance measures d1 and d2 in R are induced  by d, so that for all a, b : d(a, b) = d1(a1, b1) + d2(a2, b2). The simplest and most important case is setting d, d1, and d2 to be squared Euclidean distances in respective spaces.In other words, we are making use of the separability of the squared Euclidean distance in product spaces. The entire algorithm is based on this choice, and your design would not help in this case.PS. Why would you need std::abs() at all? And why not just std::array<T, N> instead of Point<N, T>?