函数模板

函数模板主要是泛型在函数的中的应用,通过泛型可以让函数处理各种各样的数据类型

简单的列子

  1. #include <iostream>
  2. using namespace std;
  3. template <typename T> //定义泛型T
  4. T add (T t1, T t2) {
  5. return t1 + t2;
  6. }
  7. int main () {
  8. cout << add(10.5, 0.8) << endl;
  9. }

上面的例子中首先定义了泛型T,然后在add函数中使用了泛型,typename关键字也可以写成class。

明确指定类型
  1. #include <iostream>
  2. #include <string>
  3. using namespace std;
  4. template <typename T, typename E> //定义泛型T
  5. E add (T t, E e) {
  6. if (t > 1)
  7. return e + "1";
  8. else
  9. return e + "1.5";
  10. }
  11. int main () {
  12. cout << add<int, string>(10, "hello") << endl;
  13. }

上面的代码中我们在调用add时显示的指定传入的类型

函数模板的重载

函数的模板的重载可函数的重载一个道理,都是通过函数名和函数参数列表来确定的

  1. #include <iostream>
  2. #include <string>
  3. using namespace std;
  4. template <typename T>
  5. T test(T t) {
  6. return t;
  7. }
  8. template <typename T>
  9. T test(T t, int n) {
  10. return n;
  11. }
  12. int main () {
  13. cout << test<int>(3) << endl;
  14. cout << test<float>(3.5, 10) << endl;
  15. }

第一个test(3)会调用第一个函数模板,而 test(3.5, 10)会调用第二函数模板

函数包装器

模板函数中不仅能接受普通类型作为参数,还能接受函数。当使用函数作为参数时,需要用到函数包装器

  1. #include <iostream>
  2. #include <functional>
  3. using std::cout;
  4. using std::endl;
  5. using std::function;
  6. template <typename V, typename F>
  7. V add (V v1, V v2, F f) {
  8. return f(v1, v2);
  9. }
  10. int main () {
  11. function<int(int, int)> fun = [](int v1, int v2) {
  12. return v1 + v2;
  13. };
  14. cout << add(1, 2, fun) << endl;
  15. }

上面的代码中需引入functional库,并定义了一个函数。

  1. function<int(int, int)> fun = [](int v1, int v2) {
  2. return v1 + v2;
  3. };

中括号中第一个int表示返回值类型,后面的小括号表示函数接受的参数。函数包装器的实质时函数指针。通过函数包装器我们可以在一个函数内部定义一个函数了。

函数包装器指向外部函数
  1. #include <iostream>
  2. #include <functional>
  3. using namespace std;
  4. void test(int i, int j) {
  5. cout << i << j << endl;
  6. }
  7. int main () {
  8. function<void(int, int)> fun = test;
  9. fun(1,3);
  10. }

引用包装器

要想在函数模板内部修改传入的值,需要传递变量的引用或者指针,一般情况下,我们会将变量的引用传递进去,这时将函数模板参数设置为引用或者使用引用包装器。

函数接受引用
  1. #include <iostream>
  2. #include <string>
  3. using namespace std;
  4. template <typename T>
  5. void test(T t) {
  6. t = 100;
  7. }
  8. int main () {
  9. int a = 10;
  10. test<int&>(a);
  11. cout << a << endl;
  12. }
使用引用包装器

引用包装器有些问题,尽量避免使用

  1. #include <iostream>
  2. #include <functional>
  3. using namespace std;
  4. template <typename T>
  5. void test(T t) {
  6. t += 100;
  7. }
  8. int main () {
  9. int a = 10;
  10. test(ref(a));
  11. cout << a << endl;
  12. }

上面的代码中去掉模板中的+号就会便宜错误

c++之旅:函数模板的更多相关文章

  1. c++函数模板作为类的成员函数,编译报错LNK2019的解决方法

    为了使某个类的成员函数能对不同的参数进行相同的处理,需要用到函数模板,即template<typename T> void Function(). 编译时报错LNK2019 解决方法: 1 ...

  2. C++STL - 函数模板

    模板主要是为了泛型编程,做到与类型无关 模板有函数模板和类模板,本文主要整理的是函数模板 1.函数模板定义 template<typename 类型形参1,typename 类型形参2,...& ...

  3. 使用getopt_long来解析参数的小函数模板

    getopt_long原型 #define no_argument 0 #define required_argument 1 #define optional_argument 2 struct o ...

  4. C++函数重载和函数模板

    1.函数重载 这是小菜鸟写的一个例子. 函数重载应该注意以下几点: 1.1重载函数有类似的功能: 1.2只能以参数的类型(形参个数和类型)来重载函数, int max(int a,int b);flo ...

  5. 零值初始化&字符串常数作为函数模板参数

    1.在定义一个局部变量时,并希望该局部变量的初始化一个值,可以显示调用其默认构造函数,使其值为0(bool类型默认值为false). template <typename T> void ...

  6. 让gcc支持成员函数模板的trick

    让gcc支持成员函数模板的trick 罗朝辉 (http://www.cnblogs.com/kesalin/) 本文遵循“署名-非商业用途-保持一致”创作公用协议   gcc 4.7.3 不支持成员 ...

  7. 不可或缺 Windows Native (16) - C++: 函数重载, 缺省参数, 内联函数, 函数模板

    [源码下载] 不可或缺 Windows Native (16) - C++: 函数重载, 缺省参数, 内联函数, 函数模板 作者:webabcd 介绍不可或缺 Windows Native 之 C++ ...

  8. Effective C++ -----条款45:运用成员函数模板接受所有兼容类型

    请使用member function templates(成员函数模板)生成”可接受所有兼容类型“的函数. 如果你声明member templates 用于“泛化copy构造”或“泛化assignme ...

  9. c++ 左值右值 函数模板

    1.先看一段代码,这就是一种函数模板的用法,但是红色的部分如果把a写成a++或者写成一个常量比如1,都是编译不过的,因为如果是a++的话,实际上首先是取得a的 值0,而0作为一个常量没有地址.写成1也 ...

随机推荐

  1. Linux GCC编译使用动态、静态链接库 (转)

    原文出处:http://blog.csdn.net/a600423444/article/details/7206015 在windows下动态链接库是以.dll后缀的文件,二在Linux中,是以.s ...

  2. .Net CCNet C#6.0 自动化编译问题解决

    一.问题描述 由于C#6.0一些新的语法特性,导致先前部署的CCNet持续集成平台出现问题,无论是手动还是命令行均不能编译.   二.解决方案 1.下载BuildTools_Full.exe,地址:h ...

  3. PDF.NET数据开发框架实体类操作实例

    PDF.NET数据开发框架实体类操作实例(MySQL)的姊妹篇,两者使用了同一个测试程序,不同的只是使用的类库和数据库不同,下面说说具体的使用过程. 1,首先在App.config文件中配置数据库连接 ...

  4. Maven创建一个Web项目

    我们可以通过命令行或者直接使用Eclipse创建一个maven webapp项目:通过命令行创建在命令行中输入如下格式的命令将会创建一个新的maven webapp项目:mvn archetype:g ...

  5. PMP十大知识领域整理

    2018-7-28至2018-12-8历时4个多月,学写了PMP(拍马屁),感觉自己经历了,哇-唉-哦-嗯这四个阶段 刚开始觉得如遇圣经,被PMP的知识体系和老师的精彩课程深深震撼! 后来觉得很多东西 ...

  6. vue 二级列表折叠面板

    请求出来的数据是二级列表,需要点击一级列表展开相应的二级列表 data(){ return { info: [ {name:'一级菜单1',lists:[{price:1},{price:2}]}, ...

  7. Maven 构建Spring-Boot工程报错

    Execution default of goal org.springframework.boot:spring-boot-maven-plugin:1.5.6.RELEASE:repackage ...

  8. 关于navicat 系列软件一点击菜单栏就闪退

    navicat 系列软件一点击菜单栏就闪退 多次卸载安装都出现了闪退的现象  后来发现,原来是启动了有道词典屏幕取词才会出现这种现象,关了有道就没事.

  9. Spring的AOP细节理解

    什么是AOP?AOP:是面向切面编程,是对面向对象编程(oop)的一种补充,为什么需要AOP?例如在我们做一个计算器,要求我们每次运行对应的功能(也就是进行运算时)都要输出日志,以便于知道程序是怎么运 ...

  10. uitextFiled字数输入限制

    - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementS ...