C++11 模板实参代入失败

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

使用C++实现“泛型编程”必然离不开模板的使用,模板简化了程序设计,简化了实现,解决了代码臃肿的问题。像STL(Standard Templete Library)里的函数基本都使用了模板。


一、实参代入是什么?

当对函数模板的一组实参查找最佳匹配时,编译器会检查实参的使用是否符合函数模板
的完整声明(包括返回类型)的要求。如果找不到匹配的选项,模板无法完成实例化。

二、具体例子

1.实参代入成功

代码如下(示例):

#include <iostream>
#include <vector>

using namespace std;

template<typename Iter>
typename Iter::value_type mean(Iter first, Iter last) {
    
    
    return *first;//随便写的
}

void test_1(){
    
    
	vector<double> v(2);//这个地方一定要有值,否则*first崩溃
	mean(v.begin(), v.end());
}

上面的代码是实参代入成功的例子,不做过多的讨论,请看下面失败的例子:

#include <iostream>
#include <vector>

using namespace std;

template<typename Iter>
typename Iter::value_type mean(Iter first, Iter last) {
    
    
    return *first;//随便写的
}

void test_1(){
    
    
	int *i = new int[2];
    mean(i, i + 2);
}

这里直接报错,函数模板无法实例化,照理说迭代器也是一种指针,看起来拥有相当高的匹配度,那么问题出在哪里呢?

细心的同学已经发现了,问题就出在这一句“typename Iter::value_type”。上面已经说了,模板实参需要严格匹配,int内置类型,没有value_type这个成员。当然,不只int这种内置类型,所有不带value_type的类型(包括自定义类型)都无法实例化。

关于value_type不是本章讨论的重点,你只需要直到这个是迭代器萃取里面的东西就行了。请看标准库源代码:

  /// Partial specialization for pointer types.
  template<typename _Tp>
    struct iterator_traits<_Tp*>
    {
    
    
      typedef random_access_iterator_tag iterator_category;
      typedef _Tp                         value_type;
      typedef ptrdiff_t                   difference_type;
      typedef _Tp*                        pointer;
      typedef _Tp&                        reference;
    };

迭代器萃取不是本章讨论的重点,你只需要直到只有满足参数严格匹配才能实例化,只不过满足上面的模板函数的基本是容器类型

2.解决方法

我们只需要给它另外定义一个版本即可。

代码如下(示例):

#include <iostream>
#include <vector>

using namespace std;

template<typename Iter>
typename Iter::value_type mean(Iter first, Iter last) {
    
    
    return *first;//随便写的
}

template<typename T>
T mean(T *first, T *last) {
    
    
    return *first;
}

void test_1(){
    
    
	int *i = new int[2];
    mean(i, i + 2);
}

编译器会自动匹配第二个版本,第一个版本也会保留,这下可以正常编译了。


总结

在生成一个候选函数来解析一个函数调用的过程中,如果编译器发现生成一个模
板特例化是无意义的,就不会将它加入到重载候选集中。如果一个模板特例化版本会导致类型
错误,它就被认为是无意义的。

猜你喜欢

转载自blog.csdn.net/jiexijihe945/article/details/131212718