STL源码之iterator实现

        iterator是容器和算法之间的粘合剂,为算法提供对于容器的操作,以下是关系图(继承):

        我们拿到一个类型,先判断是不是原生指针(const和非const),如果是原生指针,那我们就进行萃取,将其型别萃取成random型别;

template <class T>
    struct iterator_traits<T*>
    {
        typedef random_access_iterator_tag           iterator_category;
        typedef T                                    value_type;
        typedef T* pointer;
        typedef T& reference;
        typedef ptrdiff_t                            difference_type;
    };

         如果不是原生指针,那我们就要进行判断,看萃取出来的类类型是否具有iterator_category;

    template <class T>
    struct has_iterator_cat
    {
    private:
        struct two { char a; char b; };   
        template <class U> static two test(...);    // 存在两个字符的结构体还是说只是一个 
        template <class U> static char test(typename U::iterator_category* = 0);  
        // 运用了SFINAE技巧,若有iterator_category属性,则会优先匹配到
    public:
        static const bool value = sizeof(test<T>(0)) == sizeof(char);     // 看参数是不是true--这就是有iterator_category 
    };
	//	 这个类是一个判断模板类中是否含有typename U::iterator_category*,设计非常巧妙

        如果具有iterator_category,那就看看是不是Input和output_iterator的子类;

    template <class Iterator>
    struct iterator_traits_helper<Iterator, true>
        : public iterator_traits_impl<Iterator,
        std::is_convertible<typename Iterator::iterator_category, input_iterator_tag>::value ||
        std::is_convertible<typename Iterator::iterator_category, output_iterator_tag>::value>   // 分类是input类或者output类 
    {
    };

        iterator_traits_impl<Iterator, true>  是萃取出迭代器的特性,也就是说在                          struct iterator_traits_helper<Iterator, true>中,如果迭代器型别是Input和output_iterator的子类,那我就进行萃取并且进行typedef;

    template <class Iterator>
    struct iterator_traits_impl<Iterator, true>   // 如果说有iterator_categort的特性就去萃取; 
    {
        typedef typename Iterator::iterator_category iterator_category;
        typedef typename Iterator::value_type        value_type;
        typedef typename Iterator::pointer           pointer;
        typedef typename Iterator::reference         reference;
        typedef typename Iterator::difference_type   difference_type;
    };

        所以萃取机继承struct iterator_traits_helper即可,完美闭环~

    template <class Iterator>     // 继承关系 
    struct iterator_traits
        : public iterator_traits_helper<Iterator, has_iterator_cat<Iterator>::value> {};

逻辑图如下:

        这样看起来萃取机源码的逻辑就比较简洁了;

         那问题来了,我们要先去萃取出五种型别,并且要对型别之间的关系进行判断,那么五种型别和之间的关系如下:

    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 <class Iterator>
    typename iterator_traits<Iterator>::iterator_category
        iterator_category(const Iterator&)
    {
        typedef typename iterator_traits<Iterator>::iterator_category Category;
        return Category();
    }

剩下的反转迭代器这些就不讲了,问题又来了,我们使用迭代器的时候一般是 iterator<vector>::iter = vec.begin();   我们可以通过*iter来提取iter处的值,以及++iter来使得迭代器向前移动,这些迭代器的具体运算符重载其实是在具体的容器中实现的,因为不同容器++所实现的才做其实是可能不一样,例如list和vector的++;

        具体迭代器thin_stl的源码如下:

#pragma once
#ifndef MYTINYSTL_ITERATOR_H_
#define MYTINYSTL_ITERATOR_H_

// 这个头文件用于迭代器设计,包含了一些模板结构体与全局函数,

#include <cstddef>


namespace mystl
{

    // 五种迭代器类型
    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 {};   // 最高效率的进行元素操作; 

    // iterator 模板
    template <class Category, class T, class Distance = ptrdiff_t,
        class Pointer = T*, class Reference = T&>
        struct iterator
    {
        typedef Category                             iterator_category;
        typedef T                                    value_type;
        typedef Pointer                              pointer;
        typedef Reference                            reference;
        typedef Distance                             difference_type;
    };

    // iterator traits

    template <class T>
    struct has_iterator_cat
    {
    private:
        struct two { char a; char b; };   
        template <class U> static two test(...);    // 存在两个字符的结构体还是说只是一个 
        template <class U> static char test(typename U::iterator_category* = 0);  
        // 运用了SFINAE技巧,若有iterator_category属性,则会优先匹配到
    public:
        static const bool value = sizeof(test<T>(0)) == sizeof(char);     // 看参数是不是true--这就是有iterator_category 
    };
	//	 这个类是一个判断模板类中是否含有typename U::iterator_category*,设计非常巧妙
    template <class Iterator, bool>
    struct iterator_traits_impl {};

    template <class Iterator>
    struct iterator_traits_impl<Iterator, true>   // 如果说有iterator_categort的特性就去萃取; 
    {
        typedef typename Iterator::iterator_category iterator_category;
        typedef typename Iterator::value_type        value_type;
        typedef typename Iterator::pointer           pointer;
        typedef typename Iterator::reference         reference;
        typedef typename Iterator::difference_type   difference_type;
    };

    template <class Iterator, bool>
    struct iterator_traits_helper {};

    template <class Iterator>
    struct iterator_traits_helper<Iterator, true>
        : public iterator_traits_impl<Iterator,
        std::is_convertible<typename Iterator::iterator_category, input_iterator_tag>::value ||
        std::is_convertible<typename Iterator::iterator_category, output_iterator_tag>::value>   // 分类是input类或者output类 
    {
    };

    // 萃取迭代器的特性
    template <class Iterator>     // 继承关系 
    struct iterator_traits
        : public iterator_traits_helper<Iterator, has_iterator_cat<Iterator>::value> {};

    // 针对原生指针的偏特化版本
    template <class T>
    struct iterator_traits<T*>
    {
        typedef random_access_iterator_tag           iterator_category;
        typedef T                                    value_type;
        typedef T* pointer;
        typedef T& reference;
        typedef ptrdiff_t                            difference_type;
    };

    template <class T>
    struct iterator_traits<const T*>
    {
        typedef random_access_iterator_tag           iterator_category;
        typedef T                                    value_type;
        typedef const T* pointer;
        typedef const T& reference;
        typedef ptrdiff_t                            difference_type;
    };

    template <class T, class U, bool = has_iterator_cat<iterator_traits<T>>::value>
    struct has_iterator_cat_of
        : public m_bool_constant<std::is_convertible<
        typename iterator_traits<T>::iterator_category, U>::value>
    {
    };

    // 萃取某个迭代器的 category
    template <class Iterator>
    typename iterator_traits<Iterator>::iterator_category
        iterator_category(const Iterator&)
    {
        typedef typename iterator_traits<Iterator>::iterator_category Category;
        return Category();
    }

    // 萃取某个迭代器的 distance_type
    template <class Iterator>
    typename iterator_traits<Iterator>::difference_type*
        distance_type(const Iterator&)
    {
        return static_cast<typename iterator_traits<Iterator>::difference_type*>(0);
    }

    // 萃取某个迭代器的 value_type
    template <class Iterator>
    typename iterator_traits<Iterator>::value_type*
        value_type(const Iterator&)
    {
        return static_cast<typename iterator_traits<Iterator>::value_type*>(0);
    }

    // 以下函数用于计算迭代器间的距离

    // distance 的 input_iterator_tag 的版本
    template <class InputIterator>
    typename iterator_traits<InputIterator>::difference_type
        distance_dispatch(InputIterator first, InputIterator last, input_iterator_tag)
    {
        typename iterator_traits<InputIterator>::difference_type n = 0;
        while (first != last)
        {
            ++first;
            ++n;
        }
        return n;
    }

    // distance 的 random_access_iterator_tag 的版本
    template <class RandomIter>
    typename iterator_traits<RandomIter>::difference_type
        distance_dispatch(RandomIter first, RandomIter last,
            random_access_iterator_tag)
    {
        return last - first;
    }

    template <class InputIterator>
    typename iterator_traits<InputIterator>::difference_type
        distance(InputIterator first, InputIterator last)
    {
        return distance_dispatch(first, last, iterator_category(first));
    }

    // 以下函数用于让迭代器前进 n 个距离

    // advance 的 input_iterator_tag 的版本
    template <class InputIterator, class Distance>
    void advance_dispatch(InputIterator& i, Distance n, input_iterator_tag)
    {
        while (n--)
            ++i;
    }

    // advance 的 bidirectional_iterator_tag 的版本
    template <class BidirectionalIterator, class Distance>
    void advance_dispatch(BidirectionalIterator& i, Distance n, bidirectional_iterator_tag)
    {
        if (n >= 0)
            while (n--)  ++i;
        else
            while (n++)  --i;
    }

    // advance 的 random_access_iterator_tag 的版本
    template <class RandomIter, class Distance>
    void advance_dispatch(RandomIter& i, Distance n, random_access_iterator_tag)
    {
        i += n;
    }

    template <class InputIterator, class Distance>
    void advance(InputIterator& i, Distance n)
    {
        advance_dispatch(i, n, iterator_category(i));
    }

    /*****************************************************************************************/

    // 模板类 : reverse_iterator
    // 代表反向迭代器,使前进为后退,后退为前进
    template <class Iterator>
    class reverse_iterator
    {
    private:
        Iterator current;  // 记录对应的正向迭代器

    public:
        // 反向迭代器的五种相应型别
        typedef typename iterator_traits<Iterator>::iterator_category iterator_category;
        typedef typename iterator_traits<Iterator>::value_type        value_type;
        typedef typename iterator_traits<Iterator>::difference_type   difference_type;
        typedef typename iterator_traits<Iterator>::pointer           pointer;
        typedef typename iterator_traits<Iterator>::reference         reference;

        typedef Iterator                                              iterator_type;
        typedef reverse_iterator<Iterator>                            self;

    public:
        // 构造函数
        reverse_iterator() {}
        explicit reverse_iterator(iterator_type i) :current(i) {}
        reverse_iterator(const self& rhs) :current(rhs.current) {}

    public:
        // 取出对应的正向迭代器
        iterator_type base() const
        {
            return current;
        }

        // 重载操作符
        reference operator*() const
        { // 实际对应正向迭代器的前一个位置
            auto tmp = current;
            return *--tmp;
        }
        pointer operator->() const
        {
            return &(operator*());
        }

        // 前进(++)变为后退(--)
        self& operator++()
        {
            --current;
            return *this;
        }
        self operator++(int)
        {
            self tmp = *this;
            --current;
            return tmp;
        }
        // 后退(--)变为前进(++)
        self& operator--()
        {
            ++current;
            return *this;
        }
        self operator--(int)
        {
            self tmp = *this;
            ++current;
            return tmp;
        }

        self& operator+=(difference_type n)
        {
            current -= n;
            return *this;
        }
        self operator+(difference_type n) const
        {
            return self(current - n);
        }
        self& operator-=(difference_type n)
        {
            current += n;
            return *this;
        }
        self operator-(difference_type n) const
        {
            return self(current + n);
        }

        reference operator[](difference_type n) const
        {
            return *(*this + n);
        }
    };

    // 重载 operator-
    template <class Iterator>
    typename reverse_iterator<Iterator>::difference_type
        operator-(const reverse_iterator<Iterator>& lhs,
            const reverse_iterator<Iterator>& rhs)
    {
        return rhs.base() - lhs.base();
    }

    // 重载比较操作符
    template <class Iterator>
    bool operator==(const reverse_iterator<Iterator>& lhs,
        const reverse_iterator<Iterator>& rhs)
    {
        return lhs.base() == rhs.base();
    }

    template <class Iterator>
    bool operator<(const reverse_iterator<Iterator>& lhs,
        const reverse_iterator<Iterator>& rhs)
    {
        return rhs.base() < lhs.base();
    }

    template <class Iterator>
    bool operator!=(const reverse_iterator<Iterator>& lhs,
        const reverse_iterator<Iterator>& rhs)
    {
        return !(lhs == rhs);
    }

    template <class Iterator>
    bool operator>(const reverse_iterator<Iterator>& lhs,
        const reverse_iterator<Iterator>& rhs)
    {
        return rhs < lhs;
    }

    template <class Iterator>
    bool operator<=(const reverse_iterator<Iterator>& lhs,
        const reverse_iterator<Iterator>& rhs)
    {
        return !(rhs < lhs);
    }

    template <class Iterator>
    bool operator>=(const reverse_iterator<Iterator>& lhs,
        const reverse_iterator<Iterator>& rhs)
    {
        return !(lhs < rhs);
    }

} // namespace mystl

#endif // !MYTINYSTL_ITERATOR_H_

参考资料:侯捷老师《stl源码剖析》

                  thin_stl项目

                @深度学习可好玩了   C++:STL中的萃取器traits

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值