如何在 c++ 中使用泛型函数
How to use generic function in c++?
我写了这段代码,如果我取消注释倒数第二行,我会得到错误 - "模板参数推断/替换失败:"。是因为C++中泛型函数的某些限制吗?此外,我的程序不会为数组b
打印浮动答案。我能为此做些什么吗?(很抱歉在一篇文章中问了 2 个问题。
PS:我刚刚开始学习C++。
#include <iostream>
using namespace std;
template <class T>
T sumArray( T arr[], int size, T s =0)
{
int i;
for(i=0;i<size;i++)
{ s += arr[i];
}
return s;
}
int main()
{
int a[] = {1,2,3};
double b[] = {1.0,2.0,3.0};
cout << sumArray(a,3) << endl;
cout << sumArray(b,3) << endl;
cout << sumArray(a,3,10) << endl;
//cout << sumArray(b,3,40) << endl; //uncommenting this line gives error
return 0;
}
编辑 1:将 40 更改为 40.0 后,代码有效。这是我得到的输出:
6
6
16
46
在第二种情况下,我仍然没有得到浮动答案。有什么建议吗?
原因是编译器无法推断出T
的类型。
它应该如何理解您的最后一个示例的T
是什么?第一个参数(b
(的类型是double[]
,而在函数定义中是T[]
的。因此,看起来T
应该是double
.但是,第三个参数(40
(的类型是int
的,所以看起来T
应该int
。因此错误。
将40
更改为40.0
使其正常工作。另一种方法是在模板声明中使用两种不同的类型:
#include <iostream>
using namespace std;
template <class T, class S = T>
T sumArray( T arr[], int size, S s =0)
{
int i;
T res = s;
for(i=0;i<size;i++)
{ res += arr[i];
}
return res;
}
int main()
{
int a[] = {1,2,3};
double b[] = {1.0,2.0,3.1};
cout << sumArray(a,3) << endl;
cout << sumArray(b,3) << endl;
cout << sumArray(a,3,10) << endl;
cout << sumArray(b,3,40) << endl; //uncommenting this line gives error
return 0;
}
请注意,我必须显式地将s
转换为T
,否则最后一个示例将丢失小数部分。
但是,此解决方案仍然不适用于sumArray(a,3,10.1)
,因为它会10.1
投射到int
,因此如果这也是一个可能的用例,则需要更准确的处理。使用 c++11 功能的完整工作示例可能如下所示
template <class T, class S = T>
auto sumArray(T arr[], int size, S s=0) -> decltype(s+arr[0])
{
int i;
decltype(s+arr[0]) res = s;
...
此模板函数的另一个可能的改进是自动扣除数组大小,请参阅TartanLlama的答案。
sumArray(b,3,40)
40
的类型是int
,但b
的类型是double[3]
。当您将这些作为参数传入时,编译器会获得T
冲突的类型。
解决此问题的一种简单方法是传入double
:
sumArray(b,3,40.0)
但是,最好通过添加另一个模板参数来允许在调用站点进行转换。您还可以添加一个来推断数组的大小,这样您就不需要显式传递它:
template <class T, class U=T, std::size_t size>
U sumArray(T (&arr) [size], U s = 0)
U
参数默认为 T
以支持 s
的默认值。请注意,要推断数组的大小,我们需要传递对它的引用,而不是按值传递,这将导致它衰减到指针。
调用现在如下所示:
sumArray(b,40)
现场演示
in
template <class T>
T sumArray( T arr[], int size, T s =0)
^ ^
两者(可推导的(T
应该匹配。
在sumArray(b, 3, 40)
中,第一个是double
,第二个是int
。
有几种方法可以解决问题
在呼叫站点,呼叫
sumArray(b, 3, 40.0)
或sumArray<double>(b, 3, 40);
使用额外参数:
template <typename T, typename S> auto sumArray(T arr[], int size, S s = 0)
返回类型可以是
T
、S
或decltype(arr[0] + s)
,具体取决于您的需求。使参数不可推导:
template <typename T> struct identity { using type = T;}; // or template<typename T> using identity = std::enable_if<true, T>; template <typename T> T sumArray(T arr[], int size, typename identity<T>::type s = 0)
应该是
sumArray(b,3,40.0)
所以,T
将被推导出为double
.在您的代码中,它是int
.
当推导失败时,另一种选择是明确地告诉编译器你的意思:
cout << sumArray<double>(b,3,40) << endl;
T
应该int
还是double
。
您可能需要执行以下操作,以保留传递类型的最高精度:
template <class T, class S>
std::common_type_t <T, S> sumArray (T arr [], std::size_t size, S s = 0)
{
std::common_type_t <T, S> sum = s;
for (std::size_t i = 0; i != size; ++i)
{
sum += arr[i];
}
return sum;
}
但是,您正在编写的函数已经存在。它std::accumulate
:
std::cout << std::accumulate (std::begin (b), std::end (b), 0.0) << std::endl;
模板只接受一种类型的数据,例如,如果您发送一个双精度数组,则运行时将推断
:模板 = 双[]
所以每次他看到它时,他都会期待一系列的双打。
sumArray(b,3,40)
传递"b"(这是一个双精度数组(,但随后传递运行时无法隐式转换为双精度的"40"。
所以代码
sumArray(b,3,40.0)
将工作
- 链表的泛型函数remove()与成员函数remove)
- 以特征类型作为参数的泛型函数回调
- 传递非泛型函数的最有效方法是什么?
- 泛型函数反向打印任何矢量,编译器出错
- 是否可以在C++中创建泛型函数指针?
- 将泛型函数及其参数传递给元函数
- C++ 中的泛型函数持有者
- C++ 验证使泛型函数
- 两个不同流的泛型函数
- 如何覆盖 'const T&' 和 'T&&' 的泛型函数,其中 T 可以作为引用?
- 如何创建公开泛型函数的 DLL
- 为什么 std::apply 使用泛型函数失败
- 在某个值范围内生成 BST 的泛型函数
- 无法在循环中实例化泛型函数
- MISRA C++规则 14-5-1:在与类型关联的命名空间中声明的泛型函数模板的名称
- 使用泛型函数调用打印结构的所有嵌套成员变量
- C++ 使用数组作为参数创建泛型函数
- 泛型函数是否可以用于对结构求和
- C++为所有 std::sets 编写泛型函数
- 指向类成员函数的泛型函数指针