`
kmplayer
  • 浏览: 509940 次
  • 性别: 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五大原则之...

    深入实践C++模板编程 源码

    在深入实践C++模板编程的过程中,我们不仅可以理解模板的基本概念,还可以掌握其高级特性和应用技巧。 首先,我们要理解模板的两种主要形式:函数模板和类模板。函数模板用于定义通用的函数,例如`std::swap`,它...

    VC++深入理解源码

    《VC++深入理解源码》是一本专注于解析VC++编程语言内部机制的书籍,作者孙鑫通过详尽的代码分析,带领读者深入了解VC++的源码实现,旨在提高读者对C++编译器、运行库以及相关开发工具的深度认识。这本书不仅适合有...

    深入理解c++11pdf

    《深入理解C++11》是一本专注于C++11...总的来说,《深入理解C++11》这本书详尽地探讨了C++11的新特性,包括对多态性、继承构造函数和模板使用的增强,这些改进使得C++更加强大且易用,提高了代码的可靠性和可维护性。

    电子书 深入理解C++11(PDF)

    《深入理解C++11》是一本专注于C++11标准的权威指南,旨在帮助开发者全面掌握C++11引入的新特性和改进。C++11是C++语言的一个重大更新,它带来了许多新的功能和优化,使得C++在效率、可读性和安全性方面都有了显著...

    深入SharePoint模板定制

    其强大的自定义能力是其深受用户喜爱的重要原因,而“深入SharePoint模板定制”则是这一领域的核心知识。下面将详细探讨SharePoint模板定制的相关概念、方法和实践应用。 首先,SharePoint模板是预定义的网站结构,...

    深入理解C++11.pdf

    鉴于此,我将基于标题“深入理解C++11.pdf”所暗示的内容,详细阐述C++11标准中一些核心特性的知识点。 C++11是C++语言的一个重要版本更新,正式名称为ISO/IEC 14882:2011,它在2011年被国际标准化组织正式采纳。这...

    深入理解C++对象模型

    理解模板的实例化、类型推断和模板元编程,可以让我们编写出高效且可复用的代码。 8. **异常处理**:C++的异常处理机制允许程序在遇到错误时优雅地恢复。理解异常的抛出、捕获和栈展开的过程,可以提高代码的健壮性...

    深入理解JavaScript系列(.chm)

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

    《深入实践C++模板编程》(温宇杰)源码

    读者可以通过这些源码来学习如何有效地利用STL解决实际问题,理解模板的延迟特性和模板展开过程,以及如何利用模板技巧实现高效的数据结构和算法。 在深入研究C++模板编程时,会接触到一些高级主题,比如模板特化、...

    深入理解C++11完整版

    然而,我可以为您深入解释C++11语言版本的一些重要特性和设计思路,以满足您对C++11的深入理解需求。 C++11是C++编程语言的一个重大更新,它在2011年被国际标准化组织正式标准化。这个版本引入了大量新特性和改进,...

    深入理解C++11.rar

    《深入理解C++11》是一本专门为C++开发者准备的深入学习教程,它涵盖了C++11标准的全新特性和重要改进。C++11是C++编程语言的一个重大更新,引入了大量的新功能和优化,旨在提升代码的效率、可读性以及安全性。以下...

    深入学习与实践C++模板编程 值得学习

    本篇将深入探讨这两种模板的使用及其重要性。 一、函数模板 函数模板是C++中实现泛型编程的主要手段之一。它定义了一个通用函数,该函数可以在编译时根据不同的数据类型自动生成相应的实例。函数模板的基本语法如下...

    深入理解C++11

    《深入理解C++11》是一本专注于C++11标准的权威指南,该书全面地阐述了C++11的新特性和改进,为程序员提供了深入解析这一现代C++版本的宝贵资源。C++11是C++语言的一个重要里程碑,它引入了大量的新功能和优化,旨在...

    深入理解 C++ 11 PDF文档

    《深入理解C++ 11》是一本专为探索C++ 11新特性而编写的权威指南。C++ 11是C++语言的一个重要里程碑,它引入了大量的新特性和改进,旨在提升效率、安全性和可维护性,同时简化编程工作。这本书详细介绍了这些变革,...

    深入理解magento

    总结,深入理解Magento意味着要掌握其请求处理机制、页面布局设计、数据模型以及高级编程模式。这不仅需要对PHP有扎实的基础,还需要熟悉Magento的架构和设计模式。通过学习和实践,开发者能够创建出高效、可维护的...

    模板教程,模板 模板教程

    1. 模板的基础知识:理解模板的定义、类型及其在不同领域的应用。 2. HTML/CSS模板:学习如何创建和自定义HTML页面模板,以及CSS用于样式控制的重要性。 3. 响应式模板设计:探讨如何为移动设备优化模板,使其具备...

    Zabbix 模板 H3C交换机通用模板zbx_export_templates

    本文将深入探讨Zabbix与H3C交换机的集成,特别是在使用"Zabbix 模板 H3C交换机通用模板zbx_export_templates"时的知识点。 首先,我们来理解标题中的关键点——"Zabbix 模板 H3C交换机通用模板zbx_export_templates...

    《 C++模板》和《C++模板元编程》两本

    在《C++ Templates》这本书中,读者可以深入理解模板的基本概念,如模板声明、实例化、模板特化以及模板偏特化。书中可能涵盖了模板参数推断、模板元编程的入门知识,以及如何利用模板来实现泛型算法,如排序、查找...

Global site tag (gtag.js) - Google Analytics