I would like to call std::hypot with many arguments (not just 2 or 3).Mandatory requirements:fastrun at compile time when possibleNon-mandatory requirement:avoid overflow#include <cmath>#include <iostream>template <typename T>constexpr T sum2(const T v) {  return v * v;}template<typename T1, typename... Ts>constexpr T1 sum2(const T1 v1, const Ts... rest){  return v1 * v1 + sum2(rest...);}template <typename T1, typename... Ts>constexpr T1 qsum(const T1 v1, const Ts... v){  return sqrt(sum2(v1, v...));}int main(){  double a = 10.;  std::cout << qsum(1., a) << std::endl;}One bad thing is when I ask qsum(1, 1.) since the first argument is int and so the output. I would like that in this case the inputs are cast to the safer common type.
Extend number of arguments in std::hypot
c++;c++11;mathematics;template meta programming
First of all, let me just say that qsum is a really bad name for a generic hypot function. I would have called it... hypot! In fact, I'm going to do that in this answer, because it'll make the code a lot easier to read.Well, I'll call it my_hypot, because we'll be including <cmath>, and I don't want any confusion over whether we're accidentally referring to the standard library's 2-argument hypot.You have an anti-pattern in your code: you're writing things like T sum2(const T v) instead of T sum2(T v). The former is exactly equivalent to the latter as far as the caller of the function is concerned; but for the implementor of the function, the latter is strictly better:It's less typing, and more importantly, less reading for the maintainer/reviewer.It doesn't inhibit move semantics.For these reasons, it's idiomatic C++; and therefore you should follow the idiom because breaking idioms for no reason is distracting to the maintainer/reviewer.I think you could simplify your code by thinking in C++17 and then working backwards to lower the resulting code back down to C++11.In C++17, with fold-expressions, your function would be justtemplate<typename... Ts> constexpr auto my_hypot(Ts... vs) {    return sqrt(( (vs * vs) + ... ));}In C++14, though, we don't have fold-expressions, so we're going to have to replace the construct (pattern + ...) with some kind of function call; say, sum(pattern...). So our C++14 code should look liketemplate<typename... Ts>constexpr auto my_hypot(Ts... vs) {    return sqrt(sum( (vs * vs)... ));}In C++11, we need to use the trailing decltype trick to get the compiler to accept that code, since C++11 can't deduce return types (except in lambdas).template<typename... Ts>constexpr auto my_hypot(Ts... vs) -> decltype(sqrt(sum( (vs * vs)... ))) {    return sqrt(sum( (vs * vs)... ));}And there we go! Other than writing the sum function, this is a very straightforward translation of the code you want to write, into code that should be acceptable to a C++11 compiler.However, I think your code as it stands is a bit sketchy, because of the overflow issue. my_hypot(65536, 65536, 1.0) should yield 92681.9, not undefined behavior! To mitigate that issue, I agree with you that casting all of the parameters to common_type would be a good idea. Let's implement that.#include <cmath>#include <iostream>#include <type_traits>template<typename CT> constexpr CT sum() { return {}; }template<typename CT, typename T, typename... Ts>constexpr CT sum(T v, Ts... vs){    return v + sum<CT>(vs...);}template <typename... Ts>constexpr auto my_hypot(Ts... vs) -> typename std::common_type<Ts...>::type{    using CT = typename std::common_type<Ts...>::type;    return sqrt(sum<CT>( (CT(vs) * CT(vs))... ));}int main(){  std::cout << my_hypot(10., 10) << std::endl;  std::cout << my_hypot(10, 10, 10.) << std::endl;  std::cout << my_hypot(10, 10) << std::endl;}This is all the same straightforward code as before, with the possible exception of sum<CT>(). Here we're making an overload set of sum<CT>() (with no arguments) and sum<CT>(T, Ts...) (with at least one argument). By construction, both T and all the elements of Ts... will always be CT; we could static_assert that, if we wanted to. sum<CT>() returns a value-initialized CT (i.e., the zero of whatever type CT happens to be); I used {} instead of 0 just in case CT is some wacky bignum type that doesn't have an implicit conversion from int. Depending on your assumptions, 0 might be the safer choice.The really nice thing about this code is that because we constructed it by starting with C++17 and moving backward, it's easy to take this code and migrate it forward to C++14 (by removing the trailing return types) and then to C++17 (by replacing the implementation of sum with a one-liner, or inlining it altogether) as your compiler catches up. Looking at your original code, I think it would be a little bit harder to disentangle the C++11isms from the business logic of how to compute hypot. For example, you've got the subexpression v * v repeated in two different places, for no good reason that I can see. You could have factored that out... or rather, not factored it in in the first place! :) Don't repeat yourself.