首页 > 代码库 > 【effective c++】模板与泛型编程

【effective c++】模板与泛型编程

1.了解隐式接口和编译期多态

对template参数而言,接口是隐式的,基于有效表达式的约束

编译器多态:以不同的template参数具现化function templates会导致调用不同的函数

2.了解typename的双重意义

当我们声明template类型参数,class和typename的意义完全相同

template内出现的名称如果相依于某个template参数,称之为从属名称,如果从属名称在class内呈嵌套状,称之为嵌套从属名称。c++规定:如果解析器在template中遭遇一个嵌套从属名称,它便假设这名称不是个类型,除非你告诉它是。

任何时候当你想要在template中指涉一个嵌套从属类型名称,就必须在紧邻它的前一个位置放上关键字typename,typename只被用来验明嵌套从属类型名称,其他名称不该有它存在

template <typename C>void f(const  C& container,        //不允许使用typename    typename C::iterator iter); //一定要使用typename

typename必须作为嵌套从属类型名称的前缀词这一规则的例外是,typename不可以出现在base class list内的嵌套从属类型名称之前,也不可在成员初始化列表中作为base class修饰符

template <typename T>class Derived :public Base<T>::Nested{public:    explicit Derived(int x)        :Base<T>::Nested(x)    {        typename Base<T>::Nested temp;    }};
std::iterator_traits<IterT>::value_type  //类型为IterT之对象所指之物的类型

真实程序中使用typename的例子:

template <typename IterT>void workWithIterator(IterT iter){    typename std::iterator_traits<IterT>::value_type  temp(*iter);}

3.学习处理模板化基类内的名称

base class template有可能被特化,而那个特化版本可能不提供和一般性template相同的接口,故c++往往拒绝在模板化基类内寻找继承而来的名称

解决方案:对编译器承诺base class template的任何特化版本都将支持其一般(泛化)版本所提供的接口

1)在base class函数调用动作之前加上"this ->"

2)使用using声明式

3)明确指出被调用的函数位于base class内即用基类名称去调用该函数,这样会失去多态性

4.将与参数无关的代码抽离template?

5.运用成员函数模板接受所有兼容类型

同一个template的不同具现化之间并不存在什么固有关系,如果以带有base-derived关系的B、D两类型分别具现化某个template,产生出来的两个具现体并不带有base-derived关系

template<typename T>class SmartPtr{public:    template<typename U>    //对任何类型T和任何类型U,可以根据SmartPtr<U>生成一个SmartPtr<T>    SmartPtr(const SmartPtr<U>& other);};

 

6.需要类型转换时请为模板定义非成员函数

当我们编写一个class template,而它所提供之"与此template相关的"函数支持"所有参数之隐式类型转换"时,请将那些函数定义为class template内部的friend函数

7.请使用traits classes表现类型信息

traits并不是c++关键字或一个预先定义好的构件,它是一种技术,也是每一个c++程序员共同遵守的协议,允许你在编译期取得某些类型信息,traits总是被实现为struct,iterator_traits是针对迭代器的traits

iterator_traits的运作方式是,针对每一个类型IterT,在struct iterator_traits<IterT>内一定声明某个typedef名为iterator_category,为此它要求每一个用户自定义的迭代器类型必须嵌套一个typedef,名为iterator_category.

iterator_traits特别针对指针类型提供一个偏特化版本:

template<typename IterT>struct iterator_traits(IterT*){    typedef random_access_iterator_tag iterator_category;};

总结:

1)traits classes使得类型相关信息在编译器可用,它们以templates和templates特化完成实现

2)整合函数重载技术后,traits classes有可能在编译期对类型执行if...else测试

 

【effective c++】模板与泛型编程