C++ Calculate euclidean distance between tuples, for specified indices I wrote a small utility function that will take two tuples and returns the Euclidean distance for the given indices only:

#include &lt;cmath&gt;
#include &lt;tuple&gt;

namespace {
    template &lt;typename T&gt; constexpr auto sq(const T&amp; val) { return val * val; }
}

template &lt;int... I, typename... Tp&gt;
constexpr auto euclidean_distance(const std::tuple&lt;Tp...&gt;&amp; ta, const std::tuple&lt;Tp...&gt;&amp; tb) {
    return static_cast&lt;std::common_type_t&lt;std::tuple_element_t&lt;I, std::decay_t&lt;decltype(ta)&gt;&gt;...&gt;&gt;(
        sqrt(
                (
                    sq(
                        static_cast&lt;std::common_type_t&lt;std::tuple_element_t&lt;I, std::decay_t&lt;decltype(ta)&gt;&gt;...&gt;&gt;(std::get&lt;I&gt;(tb)) -
                        static_cast&lt;std::common_type_t&lt;std::tuple_element_t&lt;I, std::decay_t&lt;decltype(ta)&gt;&gt;...&gt;&gt;(std::get&lt;I&gt;(ta))
                    ) + ...
                )
            )
        );
}

constexpr std::tuple a { (int8_t)-10, -20, (uint16_t)50, "String", 1.2f };
constexpr std::tuple b { (int8_t)20, 120, (uint16_t)150, "Another", 9.1f };

int main() {
    volatile auto res_i = euclidean_distance&lt;0,1,2&gt;(a, b);
    volatile auto res_f = euclidean_distance&lt;0,1,2,4&gt;(a, b);
}


Right now it only takes tuples of completely equal type, but the template logic could be adapted to use tuples that only share similar types for the used indices.
I'd love to hear any comments and critiques!
Nice work! There's not much to improve here, but still:

Don't repeat yourself

You keep repeating the same type declaration over and over again. A simple type alias at the top of the function makes things so much cleaner:

using result_t = std::common_type_t&lt;std::tuple_element_t&lt;I, std::decay_t&lt;decltype(ta)&gt;&gt;...&gt;;


A little too trigger happy on the casts

I think this would be better without the final cast. std::sqrt() returns a double when passed integral types, and that's often desirable. Letting your users cast to an integer if they want after your function returns would be more flexible.

Prefer the namespaced version of C functions

std::sqrt is preferable over sqrt

Anonymous namespaces in headers mean almost nothing.

Your anonymous namespace may not generate a link-time symbol, but it still pollutes the global namespace for anything that includes it. sq() would probably be better off as a lambda inside of euclidean_distance() itself, or be in an actual named namespace.

Possible improvement:

It would be nice if this could be generalized to arbitrary norms. Passing functors that default to std::sqrt and sq would be really nice. Or perhaps a trait type that defines both the raising and the lowering operations in a single norm type might make sense.