qq_45564838
亦余gcx
采纳率100%
2021-01-14 11:53

没有与指定类型匹配的 重载函数 "maxn" 实例

已采纳
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;
}
  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享
  • 邀请回答

6条回答

  • include_iostream_ include_iostream_ 3月前

    顺便一提,由于处理指针指向的数组的需求非常常见,而这种情况下不可能获取数组长度,我们通常会这么写:

    #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;
    }
    

    这时,调用参数的正确性由调用者而不是被调用者来保证。(毕竟也没有更通用的办法。)

    点赞 1 评论 复制链接分享
  • include_iostream_ include_iostream_ 3月前

    这里提供一段能工作的代码:

    #include <iostream>
    #include <numeric>
    
    template <typename T, size_t sz>
    T maxn1(const T (&para)[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 (&para)[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;
    }
    
    点赞 1 评论 复制链接分享
  • include_iostream_ include_iostream_ 3月前

    第二种做法没出问题应该是容易理解的,先解释原始代码为啥报错。

    答案其实异常简单:你的函数模板声明为T[4]类型,定义却只有T&类型的,你的声明在编译阶段没出现问题,却无法链接,就是因为声明和定义对不上;你原始代码的声明和定义是重载,而不是对声明过的模板的定义。换言之,它们是两个模板,而不是同一个。编译时,编译器只处理了后一个(只有声明没有定义的话,寻找全局定义是链接器的工作,与编译器无关),而前一个只保留了调用接口却没有实现。链接时,链接器找不到对应的实现,当然就会报错了。

    点赞 1 评论 复制链接分享
  • qq_45564838 亦余gcx 3月前

    感谢

    点赞 评论 复制链接分享
  • qq_45564838 亦余gcx 3月前
    #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]));
    }

    困惑

    点赞 评论 复制链接分享
  • include_iostream_ include_iostream_ 3月前

    这个报错主要跟调用处有关,只凭借函数/函数模板的定义无法准确定位问题。方便的话请把调用处代码也贴上来 。

    顺便一提,这段代码看起来不能传递int*类和类似的指针参数(int*和int[]是完全不同的数据类型)。如果希望能对malloc分配获得的“数组”进行操作,还需要有指针形参的模板重载。

    点赞 评论 复制链接分享