我正在尝试编写一个接受不同数据类型的多个参数并返回数字总和的函数。它应该能够决定用于求和的数据类型。对于例如 如果我写add(3,1,2,3)它应该将sum作为int返回。但是,如果我写add(3,1,2.5,3.25),它应该将sum作为double返回。
我尝试使用模板,但是给出了编译时错误。这是函数
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;
}
编译错误:没有匹配函数来调用'add(int,int,int,int)'。 我认为错误即将来临,因为我传入了va_arg T,但我不知道还有什么要传递来保持它的概括。
答案 0 :(得分:2)
你应该替换
std::cout<<add(3,1,2,3);
带
std::cout<<add<int>(3,1,2,3); // explicitly, int, double, float whatever
要使代码成功运行,因为编译器无法从隐式调用中推断出类型名称。 Live code example here
您的函数返回类型T的值,但是您没有指定类型T的任何参数,这使得编译器无法推断出类型。
其他解决方案是添加适用于add(0)
的重载,并在添加类型T
时传递第一个参数。这可以实现OP的隐含扣除目标。现在编译器可以从第一个参数中推断出返回类型。
#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;
}
答案 1 :(得分:2)
为什么不使用Varidaic Templates? - Mohit Jain
如果你可以用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';
}
如果您使用MSVC ++(it doesn't work under g++)下的C ++ 11编写:
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 :(得分:-2)
我认为问题是您确定参数类型为int尝试使用
而不是:T Add(int n,...)
使用:T添加(T n,...)