#include #include #include #include #include #include template auto norm2(T const& values); namespace details { template auto norm2(T const& value, int, int) -> std::enable_if_t, T> { return value * value; } template auto norm2(T const& container, int, float) -> decltype( (*container.begin()) * (*container.begin()) ) { typename T::value_type result { }; for (auto it = container.begin(); it != container.end(); ++it) result += (*it) * (*it); return result; } template auto norm2(T const& point, float, float) -> decltype(point.x * point.x + point.y * point.y) { return point.x * point.x + point.y * point.y; } } template auto norm2(T const& values) { return details::norm2(values, 0, 0); } /* Testcases */ struct Point { int x { }; int y { }; }; struct Weird_Vector : public std::vector { using std::vector::vector; int x { 1 }; int y { 2 }; }; int main() { assert(( norm2(5) == 25 )); assert(( norm2(2.5) == 6.25 )); std::vector v { 1, 2, 3 }; assert(( norm2(v) == 14 )); std::list l { 3, 2, 4 }; assert(( norm2(l) == 29u )); std::array a { 0.5, 2.0, 0.5, 3.0 }; assert(( norm2(a) == 13.5 )); Point p { 3, 9 }; assert(( norm2(p) == 90 )); // Overlap between case #2 and case #3 Weird_Vector w { 1, 2, 3 }; assert(( norm2(w) == 14 )); }