C++进阶系列:参数推导、内嵌类型、迭代器与traits

4 篇文章 0 订阅

《STL源码剖析》学习记录:

模板编程中经常写到:

template<typename T>
void func0(T a)
{
    T aa;
    //do_sth();
    return;
}
template<typename T>
T func1()
{
    T tmp;
    //do_sth();
    return tmp;
}

当模板类型T为迭代器类型,而我们需要以迭代器所指类型为类型时,并不能如下所写:

template<typename T>
void func0(T a)
{
    *T aa;  //错误
    //do_sth();
    return;
}

template<typename T>
(*T) func1(T a) //错误
{
    //do_sth();
    return *a;
}

前者可以利用函数模板的参数推导来实现

template<typename T>
void func0(T a)
{
    //*T aa;
    func0_imp(*a);
    //do_sth();
    return;
}
template<typename T>
void func0_imp(T a)
{
    T aa;
    //do_sth();
    return;
}

后者模板参数推导机制却不能解决问题,并不能推导出函数的返回值类型。这时便需要内嵌类型来解决了。

template<typename T>
class Iterator
{
    typedef T value_type;//内嵌类型声明  
    //省略类成员...
};
template<typename I>
typename I::value_type  //返回值类型,必须加typename告诉编译器这是类型
func(I iter)
{
    return *iter;
}

对于指针类型或const需要对模板进行偏特化。
参考https://blog.csdn.net/uestc_chenmo/article/details/80412353

由此便引出了traits。traits便能够萃取出迭代器中的特性,如上述value_type等。通过增加一层traits间接性,不仅能够拥有特化版本,也能够对其特性进行更好的集成封装。
通常,迭代器常见有五种特性: value_type, difference_type, reference_type, pointer_type,iterator_category。因此这些都在 traits和其相应偏特化中提取出来。
其中,iterator_category标识根据迭代器的移动特性和对迭代器执行的操作上的区别和特性,将迭代器分为Input Iterator(只读)、Output Iterator(只写)、Forward Iterator(前向)、Bidirectional Iterator(双向)、Random Access Iterator(随机访问)五类。
struct input_iterator_tag {};
struct output_iterator_tag {};
struct forward_iterator_tag : public input_iterator_tag {};
// 然后4 5 依次单继承。STL命名规定,传入最初级类型命名参数,
//函数调用时假设传进一个更高级的参数,因为继承的原因,会沿继承向上传递调用

STL中有iterator类,该类不含任何成员,只是类型的定义,继承此类并不会有额外开销,迭代器通过继承该类可以规范地使用traits。

做笔记的时候突然想到的auto和decltype,略微试验了下,链接如下:
https://blog.csdn.net/uestc_chenmo/article/details/80444581

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值