`
kmplayer
  • 浏览: 499829 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

深入理解模板3

阅读更多
1,类模板和函数模板的区别:
实例化类模板时总是需要尖括号并且提供所有的非默认参数.
对于函数模板经常可以省略掉模板参数,不允许使用默认模板参数.
2,若一个函数的模版参数是一个独立的模板参数,则调用它的时候一定要指定它的类型,因为它的类型无法从函数参数中推断出来.
实例代码:
#include <iostream>
#include <sstream>
using namespace std;

//返回类型是一个独立的参数
template<class T>
T fromString(const string str)
{
    istringstream is(str);
    T t;
    is>>t;
    return t;
}

template<class T>
string toString(const T& t)
{
    ostringstream os;
    os<<t;
    return os.str();
}

int main()
{
    int i = 1234;
    cout << "i == \"" << toString(i) << "\"" << endl;
    float x = 567.89;
    cout << "x == \"" << toString(x) << "\"" << endl;


    i = fromString<int>(string("1234"));
    cout << "i == " << i << endl;
    x = fromString<float>(string("567.89"));
    cout << "x == " << x << endl;

    return 0;
}

3,数组维数没有被作为函数参数类型的一部分进行传递,除非这个参数是指针或引用.
实例代码:
#include <cstddef>
using namespace std;

template<size_t R, size_t C, typename T>
void init1(T a[R][C])
{
    for(size_t i = 0; i < R; ++i)
        for(size_t j = 0; j < C; ++j)
            a[i][j] = T();
}

template<size_t R, size_t C, class T>
void init2( T (&a)[R][C] ) //数组的引用作为参数传递
{
    for(size_t i = 0; i < R; ++i)
        for(size_t j = 0; j < C; ++j)
            a[i][j] = T();
}

int main()
{
    int a[10][20];
    init1<10,20>(a);  // 必须指定维数
    init2(a);         // 可以推断出来
    //init1(a); //error: no matching function for call to `init1(int[10][20])'
}


4,模板函数重载:只要编译器可以分开.
实例代码:
#include <cstring>
#include <iostream>
using namespace std;

template<typename T> const T& myMin(const T& a, const T& b)
{
    return (a < b) ? a : b;
}

const char* myMin(const char* a, const char* b)
{
    return (strcmp(a, b) < 0) ? a : b;
}

double myMin(double x, double y)
{
    return (x < y) ? x : y;
}

int main()
{
    const char *s2 = "say \"Ni-!\"", *s1 = "knights who";
    cout << myMin(1, 2) << endl;      // (template)
    cout << myMin(1.0, 2.0) << endl;  // (double)
    cout << myMin(1, 2.0) << endl;    // (double)
    cout << myMin(s1, s2) << endl;    // (constchar*)
    cout << myMin<>(s1, s2) << endl;  // 强迫编译器使用模板
    //这时比较的是两个字符串的地址.
}

5,多个重载函数可能发生冲突.
实例代码:
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;

//写一个经过封装的函数模板,调用正确的tolower版本.
template<class T>
T strToLower(T& str)
{
    //明确指定调用一个参数版本的tolower
    return tolower(str);
}

int main()
{
    string str("FJKDFJ");
    transform(str.begin(),str.end(),str.begin(),strToLower<char>);
    cout<<str<<endl;
}

6,模板函数结合容器对象的成员函数.
实例代码:
#include <iostream>
#include <vector>
#include <cstddef>
#include <algorithm>
using namespace std;

//容器类型,容器的对象类型,对象成员函数的返回类型
template<class Seq, class T, class R>
void apply(Seq& sq, R (T::*f)() const)
{
    typename Seq::iterator it = sq.begin();
    while(it != sq.end())
        ((*it++)->*f)();
}

//1个参数的const成员函数
template<class Seq, class T, class R, class A>
void apply(Seq& sq, R(T::*f)(A) const, A a) {
  typename Seq::iterator it = sq.begin();
  while(it != sq.end())
    ((*it++)->*f)(a);
}

//2个参数的const成员函数
template<class Seq, class T, class R, class A1, class A2>
void apply(Seq& sq, R(T::*f)(A1, A2) const, A1 a1, A2 a2)
{
    typename Seq::iterator it = sq.begin();
    while(it != sq.end())
        ((*it++)->*f)(a1, a2);
}

// Non-const, 0 arguments, any type of return value:
template<class Seq, class T, class R>
void apply(Seq& sq, R (T::*f)())
{
    typename Seq::iterator it = sq.begin();
    while(it != sq.end())
        ((*it++)->*f)();
}

// Non-const, 1 argument, any type of return value:
template<class Seq, class T, class R, class A>
void apply(Seq& sq, R(T::*f)(A), A a)
{
    typename Seq::iterator it = sq.begin();
    while(it != sq.end())
        ((*it++)->*f)(a);
}

// Non-const, 2 arguments, any type of return value:
template<class Seq, class T, class R,class A1, class A2>
void apply(Seq& sq, R(T::*f)(A1, A2), A1 a1, A2 a2)
{
    typename Seq::iterator it = sq.begin();
    while(it != sq.end())
        ((*it++)->*f)(a1, a2);
}

class Gromit
{
    int arf;
    int totalBarks;
public:
    Gromit(int arf = 1) : arf(arf + 1), totalBarks(0) {}
    void speak(int)
    {
        for(int i = 0; i < arf; i++)
        {
            std::cout << "arf! ";
            ++totalBarks;
        }
        cout << endl;
    }
    char eat(float) const
    {
        cout << "chomp!" << endl;
        return 'z';
    }
    int sleep(char, double) const
    {
        cout << "zzz..." << endl;
        return 0;
    }
    void sit() const
    {
        cout << "Sitting..." << endl;
    }
};

int main()
{
    vector<Gromit*> dogs;
    for(size_t i = 0; i < 5; i++)
        dogs.push_back(new Gromit(i));
    apply(dogs, &Gromit::speak, 1);
    apply(dogs, &Gromit::eat, 2.0f);
    apply(dogs, &Gromit::sleep, 'z', 3.0);
    apply(dogs, &Gromit::sit);
    for_each(dogs.begin(),dogs.end(),ptr_fun(operator delete));
}
分享到:
评论

相关推荐

    深入理解JavaScript系列

    深入理解JavaScript系列(3):全面解析Module模式 深入理解JavaScript系列(4):立即调用的函数表达式 深入理解JavaScript系列(5):强大的原型和原型链 深入理解JavaScript系列(6):S.O.L.I.D五大原则之...

    深入理解JavaScript系列(.chm)

    深入理解JavaScript系列(41):设计模式之模板方法 深入理解JavaScript系列(42):设计模式之原型模式 深入理解JavaScript系列(43):设计模式之状态模式 深入理解JavaScript系列(44):设计模式之桥接模式 ...

    深入理解C++11

    《深入理解C++11》讲解了C++11 lambda、decltype、auto、可变长模板参数、智能指针和原子操作等特性......

    深入理解c++模板中的class与typename

    模板中使用class和typename的区别 还没翻几页,当看到这段代码的时候就楞了一下。印象中上次也是看到这里一下子没弄懂,还特地搜索过的。结果再来一遍的时候还是忘了。果然好记性不如烂笔头,赶紧写篇博客mark一下。 ...

    深入理解magento

    Magento 模块开发教程 请求分发与控制器 布局、块和模板 模型和ORM基础 高级Magento模型

    深入理解机算计系统英文课件PPT

    深入理解机算计系统英文课件PPT

    哈工大CSAPP课件;深入理解计算机系统课件

    深入理解计算机系统课件,CSAPP

    深入理解JavaScript系列.chm

    该文档是根据博客园汤姆大叔的深入理解JavaScript系列(http://www.cnblogs.com/TomXu/archive/2011/12/15/2288411.html)博文整理而成,主要内容包括: 1.编写高质量JavaScript代码的基本要点 2.揭秘命名函数...

    深入理解C++11:C++11新特性解析与应用

    《深入理解C++11:C++11新特性解析与应用》主要内容:国内首本全面深入解读C++11新标准的专著,由C++标准委员会代表和IBM XL编译器中国开发团队共同撰写。不仅详细阐述了C++11标准的设计原则,而且系统地讲解了C++11...

    c++类模板学习指南

    有助于你深入地学习,理解c++类模板相关技术。由简单到复杂逐渐深入学习。

    深入理解Angular2 模板语法

    Angular模板语法主要包括以下几个部分: l 直接绑定 l 插值表达 l 属性绑定 l 事件绑定 l 双向绑定 l 样式绑定 l 模板和 * l 局部变量 首先来看一个模板例子,如下所示: import { Component, OnInit } from '@...

    深入理解C++类(下).pptx

    3模板形参的默认实参;4类模板别名与模板特例 类模板在实例化时必须显式地指明数据类型,编译器不能根据给定的数据推演出数据类型。 对于强类型的语言,变量的类型从始至终都是确定的、不变的,编译器在编译期间就...

    模板匹配技术

    更深入理解模板匹配技术,能够独立根据已知算法(相关匹配(Correlation Matching)、基于Hausdorff距离匹配方法 及考虑对场景图象距离变换(Distance Transform)的Hausdorff距离匹配方法)在MATLAB下编程实现相关...

    ACMC++算法模板速记【代码+注释】

    阅读建议:本资源适合作为ACM竞赛的备考资料,建议竞赛选手在平时练习和比赛前仔细阅读和理解模板中的算法原理和实现细节。同时,可以结合实际题目进行练习和应用,加深对算法的理解和掌握程度。

    TIPI:深入理解PHP内核-PHP内核程序详解chm文档

    通过此文档 可以全面 深入理解 PHP内核的设计、程序逻辑。有兴趣的朋友可以研究研究。

    Magento-中文开发教程

    深入理解Magento-第三章 – 布局,块和模板 深入理解Magento-第四章 – 模型和ORM基础 深入理解Magento-第五章 – Magento资源配置 深入理解Magento-第六章 – 高级Magento模型 深入理解Magento-第七章 – ...

    线性表的顺序存储C++实现(类模板实现)

    大致实现了STL中的线性表基本功能,通过对比C语言实现线性表的顺序存储可以更好的理解面向对象编程和面向过程的区别,更加深入的理解C语言和C++语言的区别。相关的文章可以在我的主页算法与数据结构专栏查看。

    自编的Smarty模板引擎

    深入理解Smarty模版引擎原理的最好教程,采用最简单最基本的功能写成的Smarty模板引擎,很容易就能理解Smarty的工作原理。

Global site tag (gtag.js) - Google Analytics