模板主要是为了泛型编程,做到与类型无关
模板有函数模板和类模板,本文主要整理的是函数模板
1.函数模板定义
template<typename 类型形参1,typename 类型形参2,...>
返回类型 函数模板名(调用形参表){函数体}
在返回类型,调用形参表和函数体中,所需要类型的地方都可以引用模板形参表中类型形参
template<typename A,typenamen B,typename _C>
A function(B arg){
    _C var;
    ...
}
 
2.使用
函数模板名<类型形参1,类型形参2,...>(调用实参表)
即用<>中的替换template<>中的内容
eg:
int i = function<int,double,string>(1.23);
char c = function<char,string,Studnet>("hello");
 
3.类型参数
类型形参:前面必须带有typename或class关键字.
类型实参:传递给函数模板的类型实参既可以是基本类型(char/int/double等),也可以是类类型(Student/Teacher),甚至可以是其他模板实例化的类型(string),同时传递给函数模板的类型实参必须满足模板实现的具体要求, 否则将引发编译错误.
#include <iostream>
using namespace std;

template<typename T>
T add (T x, T y) {
    return x + y;
}

class Integer {
public:
    Integer () : m_var (arg) {}
    friend ostream& operator<< (ostream& os,Integer const& i) {
        return os << i.m_var;
    }
    Integer const operator+ (Integer const& rhs) const {
        return m_var + rhs.m_var;
    }
private:
    int m_var;
};
int main (void) {
    cout << add<, ) << endl;
    cout << add<double> (1.3, 4.6) << endl;
    cout << add<string> ("Hello, ", "World !") << endl;
//  cout << add<char const*> ("Hello, ","World !") << endl;
    cout << add<Integer> (, ) << endl;
    ;
}
 
4.延迟编译
每个函数模板事实上都要被编译两次:
(1)第一次是在编译器看到该函数模板被定义的时候,这时的编译器只对该函数模板做一般性的语法检查(与类型无关),然后生成关于该函数模板的内部表示
(2)第二次是在编译器看到该函数模板被调用的时候,在用所提供的类型实参,结合之前生成的内部表示中的类型形参,做与类型相关的语法检查,并生成该函数模板的二进制指令代码.
 
5.隐式推断
(1)如果函数模板调用参数(园括号里的参数)的类型 相关与该模板的参数<尖括号里的参数>,那么在调用该函数模板的时候,即使不显示指定模板参数,编译器也有能力根据调用参数的类型隐式推断出正确的模板参数类型,这就叫模板参数的隐式推断.
(2)但是注意:如果编译器隐式推断的类型,和程序设计者所期望的类型不一致,有可能导致编译错误.
#include <iostream>
#include <typeinfo>
using namespace std;
template<typename T> void foo (T x, T y) {
    cout << "foo: " << typeid (x).name () << ' ' << typeid (y).name () << endl;
}
template<typename T> void bar (T const& x, T const& y) {
    cout << "bar: " << typeid (x).name () << ' ' << typeid (y).name () << endl;
}
template<typename R, typename T> R hum (T x) {
    R y;
    cout << "hum: " << typeid (x).name () << ' ' << typeid (y).name () << endl;
    return y;
}
void f1 (int x, int y) {}
void f2 (double x, double y) {}
int main (void) {
    int a, b;
    foo (a, b); // i i
    double c, d;
    bar (c, d); // d d
    ], f[];
    foo (e, f); // Pc Pc
    bar (e, f); // A256_c A256_c

//  cout << sizeof (e) << endl; // 256
//  char (*p)[256] = &e;
//  e[0] = 'C'; // *(e+0) = 'C'

    foo ("hello", "tarena"); // PKc PKc
//  bar ("hello", "tarena"); // A6_c A7_c
    bar<string> ("hello", "tarena"); // Ss Ss
    bar (string ("hello"), string ("tarena"));
    f1 (a, c); // c: double -> int
    f2 (a, c); // a: int -> double

//  int i = 1.2;
//  cout << i << endl;

//  隐式推断的同时不能隐式转换
//  foo (a, c); // c: double -> int, T=int
                // a: int -> double, T=double
    foo ((double)a, c); // d d
    foo (a, (int)c);    // i i
    foo<double> (a, c); // d d
    foo<int> (a, c);    // i i
//  a = hum (c);        // 返回值的类型不参与隐式推断
    a = hum<int> (c);   // d i
    ;
}
 
6.重载
与普通函数一样,函数模板也可以形成重载关系,类型的约束性越强的版本越被有限选择
#include <iostream>
#include <typeinfo>
#include <cstring>
using namespace std;
// 两个任意类型值的最大值
template<typename T>
T const& max (T const& x, T const& y) {
    cout << "<1" << typeid (x).name () << '>' << flush;
    return x < y ? y : x;
}
// 两个任意类型指针所指向目标的最大值
template<typename T>
T* const& max (T* const& x, T* const& y) {
    cout << "<2" << typeid (x).name () << '>' << flush;
    return *x < *y ? y : x;
}
// 两个字符指针所指向字符串的最大值
char const* const& max (char const* const& x,char const* const& y) {
    cout << "<3" << typeid (x).name () << '>' << flush;
     ? y : x;
}
/*
char const* max (char const* x,char const* y){
    cout << "<3" << typeid (x).name () << '>' << flush;
    return strcmp (x, y) < 0 ? y : x;
}
*/
// 三个任意类型值的最大值
template<typename T>
T const& max (T const& x, T const& y,
    T const& z) {
    cout << "<4" << typeid (x).name () << '>' << flush;
    return ::max (::max (x, y), z);
}
/*
// 两个字符指针所指向字符串的最大值
char const* const& max (char const* const& x,char const* const& y) {
    cout << "<3" << typeid (x).name () << '>' << flush;
    return strcmp (x, y) < 0 ? y : x;
}
*/
int main (void) {
    , b = ;
    cout << ::max (a, b) << endl;
    cout << *::max (&a, &b) << endl;
    char const* c = "ab", *d = "abc";
    cout << ::max (c, d) << endl;
    cout << ::max<> (c, d) << endl;
    cout << ::max<char const*> (c, d) << endl;
    char const* e = "abcd";
    char const* const& f = ::max (c, d, e);
    cout << f << endl;
    ";
    ::max (g, h, i);
    cout << f << endl;
    ;
}
 
 
暂时就是这些了...

C++STL - 函数模板的更多相关文章

  1. STL函数模板(即算法)一览

    查找算法 adjacent_find:找出一个串中第一个不符合次序的地方 find,find_if:找出第一个符合条件的元素 find_first_of:在一个串中寻找第一个与另一个串中任意一个元素相 ...

  2. 仿stl+函数模板

    #include<iostream> using namespace std; template<class T> void output(T begin, T end) { ...

  3. STL标准模板库介绍

    1. STL介绍 标准模板库STL是当今每个从事C++编程的人需要掌握的技术,所有很有必要总结下 本文将介绍STL并探讨它的三个主要概念:容器.迭代器.算法. STL的最大特点就是: 数据结构和算法的 ...

  4. [Reprint] C++函数模板与类模板实例解析

    这篇文章主要介绍了C++函数模板与类模板,需要的朋友可以参考下   本文针对C++函数模板与类模板进行了较为详尽的实例解析,有助于帮助读者加深对C++函数模板与类模板的理解.具体内容如下: 泛型编程( ...

  5. c++函数模板声明与定义相分离

    最近在仿写stl,发现stl源码中将模板的声明与定义写在一起实在很不优雅.自己尝试用“传统”方法,及在.h文件里声明,在.cpp文件里定义,然后在main函数里包含.h头文件,这样会报链接错误.这是因 ...

  6. c++的函数模板和类模板

    函数模板和普通函数区别结论: 函数模板不允许自动类型转化 普通函数能够进行自动类型转换 函数模板和普通函数在一起,调用规则: 1 函数模板可以像普通函数一样被重载 2 C++编译器优先考虑普通函数 3 ...

  7. 读书笔记 effective c++ Item 45 使用成员函数模板来接受“所有兼容类型”

    智能指针的行为像是指针,但是没有提供加的功能.例如,Item 13中解释了如何使用标准auto_ptr和tr1::shared_ptr指针在正确的时间自动删除堆上的资源.STL容器中的迭代器基本上都是 ...

  8. C++_进阶之函数模板_类模板

     C++_进阶之函数模板_类模板 第一部分 前言 c++提供了函数模板(function template.)所谓函数模板,实际上是建立一个通用函数,其函数类型和形参类型不具体制定,用一个虚拟的类型来 ...

  9. C++—模板(1)模板与函数模板

    1.引入 如何编写一个通用加法函数?第一个方法是使用函数重载, 针对每个所需相同行为的不同类型重新实现这个函数.C++的这种编程机制给编程者极大的方便,不需要为功能相似.参数不同的函数选用不同的函数名 ...

随机推荐

  1. 【字符编码】字符编码 && Base64编码算法

    一.前言 在前面的解决乱码的一文中,只找到了解决办法,但是没有为什么,说白了,就是对编码还是不是太熟悉,编码问题是一个很简单的问题,计算机从业人员应该也必须弄清楚,基于编码的应用有Base64加密算法 ...

  2. 从ListView逐步演变到RecyclerView

    ListView是我们开发中最常用的组件之一,在以往的PC端组件开发中,列表控件也是相当重要的,但是从桌面端到移动端,情况又有新的变化. 移动端的屏幕并不像桌面端那么大,并且移动端不可能把所有的内容都 ...

  3. JS弹出模态窗口下拉列表特效

    效果体验:http://hovertree.com/texiao/js/20/ 或者扫描二维码在手机体验: 点击选择城市后,在弹出的层中的输入框,输入英文字母 h,会有HoverTree和Hewenq ...

  4. [WCF编程]10.操作:流操作

    一.流操作概述 在默认情况下,当客户端调用服务时,服务只有在接收到完整的消息后才会被调用,同样,客户端只有在包含了调用结果的返回消息被完整接受时,才会解除对它的阻塞. 对于数据量小的消息,这种交换模式 ...

  5. 引用Microsoft.Office.Interop.Excel出现的问题

    引用Microsoft.Office.Interop.Excel出现的问题   转自:http://www.hccar.com/Content,2008,6,11,75.aspx,作者:方继祥 操作背 ...

  6. sqlserver 时间格式函数详细

    一.时间函数 在使用存储过程,sql函数的时候,会遇到一些对时间的处理.比如时间的获取与加减.这里就用到了sql自带的时间函数.下面我列出这些函数,方便日后记忆,使用. --getdate 获取当前时 ...

  7. 数三角形 bzoj 1201

    数三角形(1s 128MB)triangle [题目描述] 小苏看到一个这样的等边三角形:该等边三角形每边的长度为n且被分成n等份,于是每条边就有n-1个等分点.而整个三角形被连接两个不同边的等分点且 ...

  8. JVM垃圾回收(GC)原理

    一.基本垃圾回收算法 1.引用计数(Reference Counting) 比较古老的回收算法.原理是此对象有一个引用则增加一个引用计数,删除一个引用则较少一个引用计数.垃圾回收时,只回收引用计数为0 ...

  9. 最短路径之Floyd算法

    Floyd算法又称弗洛伊德算法,也叫做Floyd's algorithm,Roy–Warshall algorithm,Roy–Floyd algorithm, WFI algorithm. Floy ...

  10. Lind.DDD.Utils.HttpHelper关于对HttpClient的正确使用

    回到目录 官方的不一定是对的,机器最能证明一切 不知道从什么时候起,我们在写数据库连接,网络连接,文件操作时会习惯加上using,这种习惯被我们误称为一种模式,但事实上,一切事情都有因有果的,使用us ...