Adding a Variable Number of Numbers

I am trying to write a function that takes several arguments of different data types and returns the sum of numbers. He should be able to decide what type of data will be used for the amount. E.g. if I write add (3,1,2,3), it should return the amount as int. However, if I write add (3,1,2,5,3,25), it should return the amount as double.

I tried using the template, but gave a compile-time error. Here is the function

template <typename T> T add(int n, ...) { T sum = 0; va_list vl; va_start(vl,n); for(int i=0;i<n;i++) { sum += va_arg(vl,T); } va_end(vl); return sum; } int main() { std::cout<<add(3,1,2,3); return 0; } 

Compilation error: there is no corresponding function to call 'add (int, int, int, int)'. I think the error is coming because I went to va_arg T, but I don’t know what else to pass so that it is generalized.

+5
source share
3 answers

You must replace

 std::cout<<add(3,1,2,3); 

from

 std::cout<<add<int>(3,1,2,3); // explicitly, int, double, float whatever 

So that the code runs successfully, because the compiler was unable to infer the type name from the implicit call. Live code example here

Your function returns a value of type T, but you do not specify any argument of type T, which makes it impossible for the compiler to output this type.


Another solution would be to add an overload that works for add(0) , and pass the first argument to an addition of type T This can achieve the goal of implicitly deducing the OP. Now the compiler can infer the return type from the first argument.

 #include <cstdarg> #include <iostream> #include <cassert> using namespace std; int add(int n) { assert(0 == n); return 0; } template <typename T> T add(int n, T first, ...) { T sum = first; va_list vl; va_start(vl,first); for(int i=1;i<n;i++) { sum += va_arg(vl,T); } va_end(vl); return sum; } int main() { std::cout<<add(3,1,2,3); std::cout<<add(3,1.5,2.,3.5); return 0; } 

live code here

+2
source

Why not use Varidaic Templates ? - Mohit Jain

If you can write in C ++ 14:

 template<typename T> inline T sum(T t){ return t; } template<typename T, typename... Ts> inline auto sum(T t, Ts... ts){ return t+sum(ts...); } #include<iostream> int main(){ std::cout<<sum(2.5, 2)<<'\n' <<sum(2, 2.5)<<'\n' <<sum(1u, 2.5, 3.f, '0')<<'\n'; } 

If you write in C ++ 11 under MSVC ++ ( it does not work under g ++ ):

 template<typename T> inline T sum(T t){ return t; } template<typename T, typename... Ts> inline auto sum(T t, Ts... ts)->decltype(t+sum(ts...)){ return t+sum(ts...); } #include<iostream> int main(){ std::cout<<sum(2.5, 2)<<'\n' //works <<sum(2, 2.5)<<'\n' //works <<sum(1u, 2.5, 3.f, '0')<<'\n';//works under VC++, but not under g++ } 
+2
source

I think the problem is that you determined the type of the parameter as int trying to use

instead: T Add (int n, ...)

use: T Add (T n, ...)

-2
source

Source: https://habr.com/ru/post/1202522/


All Articles