template <typename T>
auto maxn(const T arr[])->T
{
int len=sizeof(arr) / sizeof(arr[0]);
T m=arr[0];
for (int i = 1; i < len; i++)
{
if (m<arr[i])
{
m=arr[i];
}
}
return m;
}
template <> char* maxn <char*>(const char* arr[])
{
return arr[0];
}
template <typename T>
auto a(T q,T w)->T
{
cout<<(q+w);
return q;
}
顺便一提,由于处理指针指向的数组的需求非常常见,而这种情况下不可能获取数组长度,我们通常会这么写:
#include <iostream>
#include <numeric>
template <typename T>
T maxn(size_t sz, T* para) {
T maxn = std::numeric_limits<T>::min();
for (size_t i = 0; i < sz; ++i) {
maxn = maxn > para[i] ? maxn : para[i];
}
return maxn;
}
int main() {
int a[] = {1, 5, 3, 4, 2};
int *p = new int[5];
p[0] = 4; p[1] = 2; p[2] = 3; p[3] = 1; p[4] = 5;
std::cout << "maxn: " << maxn(sizeof(a) / sizeof(int), a) << std::endl;
std::cout << "maxn: " << maxn(5, p) << std::endl;
delete[] p;
return 0;
}
这时,调用参数的正确性由调用者而不是被调用者来保证。(毕竟也没有更通用的办法。)
这个报错主要跟调用处有关,只凭借函数/函数模板的定义无法准确定位问题。方便的话请把调用处代码也贴上来 。
顺便一提,这段代码看起来不能传递int*类和类似的指针参数(int*和int[]是完全不同的数据类型)。如果希望能对malloc分配获得的“数组”进行操作,还需要有指针形参的模板重载。
#include <iostream>
using namespace std;
template <typename T>
auto maxn(T arr[4])-> decltype(arr[0]);
int main()
{
int a[4]={1,2,3,5};
cout<<maxn(a);
return 0;
}
template <typename T>
auto maxn(T & arr)-> decltype(arr[0])
{
int len = sizeof(arr) / sizeof(arr[0]);
decltype(arr[0]) m=arr[0];
for (int i = 1; i < len; i++)
{
if (m<arr[i])
{
m=arr[i];
}
}
return m;
}
这是我目前的想法
然后下面是报错
undefined
reference to `decltype ({parm#1}[0]) maxn<int>(int*)'
collect2.exe: error: ld returned 1 exit status
但是,如下运行则没错
int main()
{
int a[4]={1,2,3,5};
maxn(a);
return 0;
}
template <typename T>
void maxn(T & arr)
{
int len = sizeof(arr) / sizeof(arr[0]);
decltype(arr[0]) m=arr[0];
for (int i = 1; i < len; i++)
{
if (m<arr[i])
{
m=arr[i];
}
}
cout<<m;
}
其中T的类型是int [4],我是用下面这个函数获取的
template <class T>
int getArrayLen(T & array)
{
//cout<<typeid(T).name()<<"\n";
cout<<abi::__cxa_demangle(typeid(T).name(), nullptr, nullptr, nullptr)<<"\n";
return (sizeof(array) / sizeof(array[0]));
}
困惑
第二种做法没出问题应该是容易理解的,先解释原始代码为啥报错。
答案其实异常简单:你的函数模板声明为T[4]类型,定义却只有T&类型的,你的声明在编译阶段没出现问题,却无法链接,就是因为声明和定义对不上;你原始代码的声明和定义是重载,而不是对声明过的模板的定义。换言之,它们是两个模板,而不是同一个。编译时,编译器只处理了后一个(只有声明没有定义的话,寻找全局定义是链接器的工作,与编译器无关),而前一个只保留了调用接口却没有实现。链接时,链接器找不到对应的实现,当然就会报错了。
这里提供一段能工作的代码:
#include <iostream>
#include <numeric>
template <typename T, size_t sz>
T maxn1(const T (¶)[sz]) {
T maxn = std::numeric_limits<T>::min();
for (size_t i = 0; i < sz; ++i) {
maxn = maxn > para[i] ? maxn : para[i];
}
return maxn;
}
template <typename T, size_t sz>
T maxn2(const T (¶)[sz]) {
T maxn = std::numeric_limits<T>::min();
for (const T& val : para) {
maxn = maxn > val ? maxn : val;
}
return maxn;
}
int main() {
int a[] = {1, 5, 3, 4, 2};
std::cout << "maxn1: " << maxn1(a) << std::endl;
std::cout << "maxn2: " << maxn2(a) << std::endl;
return 0;
}
感谢