Effective C++(使用traits classes表现类型信息)


author:

  • luixiao1223
    title: 使用traits classes表现类型信息

工具性templates

advance,可以将迭代器移动某个距离.

template<typename IterT, typename DistT>
void advance(IterT& iter, DistT d); // 如果d<0则可以向后移动.

STL的迭代器分类

一次一步,只能读取(写入)一次

  1. istream_iterators
  2. ostream_iterators

forward 迭代器

每次移动一个位置,但是可以读取多次.STL没有这种,有的实现了单链表的slist

bidirectional

可以向前向后移动一个位置,可以读取多次.set,multiset,map,multimap,list

random access

可以进行迭代算术,可以一次性移动多个距离.vector,deque,string.

如何实现advance

这是伪代码的实现思路

template<typename IterT, typename DistT>
void advance(IterT& iter, DistT d)
{
    if (iter is a random access iterator) {
        iter += d;
    }
    else {
        if (d >= 0) { while (d--) ++iter; }
        else { while (d++) --iter; }
    }
}

如何判断类的所属类型?实际上STL中有tag信息.可以使用tag信息

struct input_iterator_tag {};
struct output_iterator_tag {};
struct forward_iterator_tag: public input_iterator_tag {};
struct bidirectional_iterator_tag: public forward_iterator_tag {};
struct random_access_iterator_tag: public bidirectional_iterator_tag {};

template<typename IterT>
struct iterator_traits;

template <...>
class deque {
public:
    class iterator {
    public:
        typedef random_access_iterator_tag iterator_category;
    };
};

template < ... >
class list {
public:
    class iterator {
    public:
        typedef bidirectional_iterator_tag iterator_category;
    };
};

// 标准库中的类型可以使用
template<typename IterT>
struct iterator_traits {
    typedef typename IterT::iterator_category iterator_category; //获取内类型中的tag类型
};

// 用户自定义类型可以使用
template<typename T>
struct iterator_traits<T*>
{
    typedef random_access_iterator_tag iterator_category; // 把指针的tag类型设置为random access
};

来实现advance看看

template<typename IterT, typename DistT>
void advance(IterT& iter, DistT d)
{
    if (typeid(typename std::iterator_traits<IterT>::iterator_category) ==
        typeid(std::random_access_iterator_tag))
        ...;
}

有编译的问题.
typeid时发生在运行期.而其他的事情时可以在编译期完成的.所以这样的设计本身就浪费了.如何提前到编译期来?
函数重载

template<typename IterT, typename DistT>
void doAdvance(IterT& iter, DistT d,
               std::random_access_iterator_tag)
{
    iter += d;
}

template<typename IterT, typename DistT>
void doAdvance(IterT& iter, DistT d,
               std::bidirectional_iterator_tag)
{
    if (d >= 0) { while (d--) ++iter; }
    else { while (d++) --iter; }
}

template<typename IterT, typename DistT>
void doAdvance(IterT& iter, DistT d,
               std::input_iterator_tag)
{
    if (d < 0 ) {
        throw std::out_of_range("Negative distance");
    }
    while (d--) ++iter;
}

这样,如果我们在此这样调用

template<typename IterT, typename DistT>
void advance(IterT& iter, DistT d)
{
    doAdvance(
        iter, d,
        typename
        std::iterator_traits<IterT>::iterator_category()
        );
}

这样就可以顺利的利用重载函数在编译期就确定要运行的时循环++还是直接+d.

TR1

这里面有很多关于traits的相关功能如
is_fundamental<T>, is_array<T>,is_base_of<T1,T2> 等等

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值