《STL源码剖析》笔记-配接器adapters

上一篇:《STL源码剖析》笔记-仿函数(函数对象)

配接器adapters在STL中起到转换、连接的作用,包括仿函数配接器(function adapter)、容器配接器(container adapter)、迭代器配接器(iterator adapter)。

容器配接器

在介绍序列式容器queue和stack时(https://blog.csdn.net/WizardtoH/article/details/82707771),说过他们就是一种容器配接器,是通过deque作为底层容器实现的。

迭代器配接器

STL提供的迭代器配接器包括insert iterators、reverse Iterators、iostream iterators。

insert iterators的作用是将一般迭代器的赋值操作转变为插入操作,有back_insert_iterator、front_insert_iterator、insert_iterator三种,分别用于尾端插入、前端插入、指定位置插入。

// 模板参数为容器对象
template <class Container>
class back_insert_iterator {
protected:
    Container* container;
public:
    typedef output_iterator_tag iterator_category;
    typedef void                value_type;
    typedef void                difference_type;
    typedef void                pointer;
    typedef void                reference;

	// 绑定容器
    explicit back_insert_iterator(Container& x) : container(&x) {}

	// 重载=操作符,转为调用push_back
    back_insert_iterator<Container>& operator=(const typename Container::value_type& value) {
        container->push_back(value);
        return *this;
    }
  
    // 屏蔽部分操作符
    back_insert_iterator<Container>& operator*() { return *this; }
    back_insert_iterator<Container>& operator++() { return *this; }
    back_insert_iterator<Container>& operator++(int) { return *this; }
};

// 辅助函数,便于调用
template <class Container>
inline back_insert_iterator<Container> back_inserter(Container& x) {
	  return back_insert_iterator<Container>(x);
}

template <class Container>
class front_insert_iterator {
protected:
    Container* container;
public:
    typedef output_iterator_tag iterator_category;
    typedef void                value_type;
    typedef void                difference_type;
    typedef void                pointer;
    typedef void                reference;

    explicit front_insert_iterator(Container& x) : container(&x) {}

	// 重载=操作符,转为调用push_front
    front_insert_iterator<Container>&operator=(const typename Container::value_type& value) {
        container->push_front(value);
        return *this;
    }
    front_insert_iterator<Container>& operator*() { return *this; }
    front_insert_iterator<Container>& operator++() { return *this; }
    front_insert_iterator<Container>& operator++(int) { return *this; }
};

template <class Container>
inline front_insert_iterator<Container> front_inserter(Container& x) {
	return front_insert_iterator<Container>(x);
}

template <class Container>
class insert_iterator {
protected:
    Container* container;
    typename Container::iterator iter;
public:
    typedef output_iterator_tag iterator_category;
    typedef void                value_type;
    typedef void                difference_type;
    typedef void                pointer;
    typedef void                reference;

    insert_iterator(Container& x, typename Container::iterator i)
        : container(&x), iter(i) {}

	// 重载=操作符,转为调用insert
    insert_iterator<Container>& operator=(const typename Container::value_type& value) {
        iter = container->insert(iter, value);
        ++iter;
        return *this;
    }
    
    insert_iterator<Container>& operator*() { return *this; }
    insert_iterator<Container>& operator++() { return *this; }
    insert_iterator<Container>& operator++(int) { return *this; }
};

template <class Container, class Iterator>
inline insert_iterator<Container> inserter(Container& x, Iterator i) {
  typedef typename Container::iterator iter;
  return insert_iterator<Container>(x, iter(i));
}

int main()
{
    std::list<int> lst = {1,2,3};
    auto backItor = std::back_inserter(lst);
    backItor = 0;									                    // 1230
    auto frontItor = std::front_inserter(lst);
    frontItor= 0;									                        // 01230
    auto insertItor = std::inserter(lst, ++lst.begin());  // 091230,在指定迭代器前插入
    insertItor = 9;

    return 0;
}

reverse Iterators的作用是将迭代器移动的操作进行倒转。

template <class Iterator>
class reverse_iterator
{
protected:
    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 x) : current(x) {}
    reverse_iterator(const self& x) : current(x.current) {}

    iterator_type base() const { return current; }

	// 重载*操作符为后退一步取值
    reference operator*() const {
        Iterator 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) const {
        return self(current - n);
    }
    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;
    }
    
    reference operator[](difference_type n) const { return *(*this + n); }
};

stream Iterators的作用是将迭代器绑定到stream对象上,包括istream和ostream。

template <class T, class Distance = ptrdiff_t>
class istream_iterator {
    friend bool
        operator== __STL_NULL_TMPL_ARGS(const istream_iterator<T, Distance>& x,
            const istream_iterator<T, Distance>& y);
protected:
    istream* stream;
    T value;
    bool end_marker;
    void read() {
        end_marker = (*stream) ? true : false;
        if (end_marker) *stream >> value;               // 将输入流赋值给value
        end_marker = (*stream) ? true : false;
    }
public:
    typedef input_iterator_tag iterator_category;
    typedef T                  value_type;
    typedef Distance           difference_type;
    typedef const T*           pointer;
    typedef const T&           reference;

    istream_iterator() : stream(&cin), end_marker(false) {}
    istream_iterator(istream& s) : stream(&s) { read(); }
    reference operator*() const { return value; }
    pointer operator->() const { return &(operator*()); }

	// 每当遇到++操作符时读入
    istream_iterator<T, Distance>& operator++() {
        read();
        return *this;
    }
    istream_iterator<T, Distance> operator++(int) {
        istream_iterator<T, Distance> tmp = *this;
        read();
        return tmp;
    }
};

template <class T>
class ostream_iterator {
protected:
    ostream* stream;
    const char* string;
public:
    typedef output_iterator_tag iterator_category;
    typedef void                value_type;
    typedef void                difference_type;
    typedef void                pointer;
    typedef void                reference;

    ostream_iterator(ostream& s) : stream(&s), string(0) {}
    ostream_iterator(ostream& s, const char* c) : stream(&s), string(c) {}

	// 每当遇到=操作符时,将value输出到输出流,同时支持分隔符
    ostream_iterator<T>& operator=(const T& value) {
        *stream << value;
        if (string) *stream << string;
        return *this;
    }
    
	// 禁止部分操作符
    ostream_iterator<T>& operator*() { return *this; }
    ostream_iterator<T>& operator++() { return *this; }
    ostream_iterator<T>& operator++(int) { return *this; }
};

int main()
{
    std::list<int> lst;
    lst.resize(5);

    std::istream_iterator<int> in(std::cin);
    std::istream_iterator<int> eof;                     // 输入结束符,windows控制台中可以用Ctrl+Z
    std::copy(in, eof, lst.begin());                      // 配合copy使用时,将输入流拷贝给lst,用到了istream_iterator的++和*操作符

	std::ostream_iterator<int> out(std::cout, ",");
    std::copy(lst.begin(), lst.end(), out);          // 配合copy使用时,将lst拷贝给输出流,当copy中使用=操作符时就进行输出

    return 0;
}

输入输出结果:
in  << 1 2 3<Ctrl + Z>
out >> 1,2,3

仿函数配接器

容器配接器包含有底层容器,迭代器配接器中包含有容器、迭代器、输入输出流程,类似的仿函数配接器包含了底层仿函数。STL中提供了几个默认的仿函数配接器,以下会进行介绍。

对返回值进行逻辑否定:not1,not2。

template <class Predicate>
class unary_negate
    : public unary_function<typename Predicate::argument_type, bool> {
protected:
    Predicate pred;
public:
    explicit unary_negate(const Predicate& x) : pred(x) {}

	// 对仿函数的结果进行逻辑否
    bool operator()(const typename Predicate::argument_type& x) const {
        return !pred(x);
    }
};

// not1,对一元仿函数进行逻辑否
template <class Predicate>
inline unary_negate<Predicate> not1(const Predicate& pred) {
    return unary_negate<Predicate>(pred);
}

template <class Predicate>
class binary_negate
    : public binary_function<typename Predicate::first_argument_type,
    typename Predicate::second_argument_type,
    bool> {
protected:
    Predicate pred;
public:
    explicit binary_negate(const Predicate& x) : pred(x) {}
	
	// 对仿函数的结果进行逻辑否
    bool operator()(const typename Predicate::first_argument_type& x,
        const typename Predicate::second_argument_type& y) const {
        return !pred(x, y);
    }
};

// not2,对二元仿函数进行逻辑否
template <class Predicate>
inline binary_negate<Predicate> not2(const Predicate& pred) {
    return binary_negate<Predicate>(pred);
}

int main()
{
	// greater原来结果是0编程了1,意义是不大于
    std::cout << std::not2(std::greater<int>())(1, 2) << std::endl;   // 1

    return 0;
}

绑定参数:bind1st,bind2nd。

template <class Operation>
class binder1st
    : public unary_function<typename Operation::second_argument_type,
    typename Operation::result_type> {
protected:
    Operation op;
    typename Operation::first_argument_type value;
public:
    binder1st(const Operation& x,
        const typename Operation::first_argument_type& y)
        : op(x), value(y) {}
    typename Operation::result_type
        operator()(const typename Operation::second_argument_type& x) const {
        return op(value, x);
    }
};

template <class Operation, class T>
inline binder1st<Operation> bind1st(const Operation& op, const T& x) {
    typedef typename Operation::first_argument_type arg1_type;
    return binder1st<Operation>(op, arg1_type(x));
}

template <class Operation>
class binder2nd
    : public unary_function<typename Operation::first_argument_type,
    typename Operation::result_type> {
protected:
    Operation op;
    typename Operation::second_argument_type value;
public:
    binder2nd(const Operation& x,
        const typename Operation::second_argument_type& y)
        : op(x), value(y) {}
    typename Operation::result_type
        operator()(const typename Operation::first_argument_type& x) const {
        return op(x, value);
    }
};

template <class Operation, class T>
inline binder2nd<Operation> bind2nd(const Operation& op, const T& x) {
    typedef typename Operation::second_argument_type arg2_type;
    return binder2nd<Operation>(op, arg2_type(x));
}

int main()
{
	// 将10绑定到equal_to的第一个参数中,返回一个仿函数对象
    auto equal10 = std::bind1st(std::equal_to<int>(), 10);
    std::cout << equal10(1) << std::endl;         // 0
    std::cout << equal10(10) << std::endl;       // 1

	// 配合使用,移除容器中所有小于等于2的元素
	// remove_if接收一个区间,并接收一个一元仿函数对象,会将区间中仿函数返回true的元素都放到为区间尾部
	// 配合erase移除区间尾部的元素
	std::vector<int> vec = { 1,2,3,4,5 };
    vec.erase(
        std::remove_if(vec.begin(), vec.end(), std::bind2nd(std::less_equal<int>(), 2)),   // 将小于等于仿函数绑定为一元仿函数对象
        vec.end()
    );
    return 0;
}

用于函数合成:compose1,compose2。这两个仿函数配接器是SGI STL特有的,不属于STL标准。

template <class Operation1, class Operation2>
class unary_compose : public unary_function<typename Operation2::argument_type,
    typename Operation1::result_type> {
protected:
    Operation1 op1;
    Operation2 op2;
public:
    unary_compose(const Operation1& x, const Operation2& y) : op1(x), op2(y) {}
    typename Operation1::result_type
        operator()(const typename Operation2::argument_type& x) const {
        return op1(op2(x));
    }
};

// 将仿函数2的结果作为仿函数1的参数
template <class Operation1, class Operation2>
inline unary_compose<Operation1, Operation2> compose1(const Operation1& op1, const Operation2& op2) {
    return unary_compose<Operation1, Operation2>(op1, op2);
}

template <class Operation1, class Operation2, class Operation3>
class binary_compose
    : public unary_function<typename Operation2::argument_type,
    typename Operation1::result_type> {
protected:
    Operation1 op1;
    Operation2 op2;
    Operation3 op3;
public:
    binary_compose(const Operation1& x, const Operation2& y,
        const Operation3& z) : op1(x), op2(y), op3(z) { }
    typename Operation1::result_type
        operator()(const typename Operation2::argument_type& x) const {
        return op1(op2(x), op3(x));
    }
};

// 将仿函数2、3的结果作为仿函数1的参数
template <class Operation1, class Operation2, class Operation3>
inline binary_compose<Operation1, Operation2, Operation3>
compose2(const Operation1& op1, const Operation2& op2, const Operation3& op3) {
    return binary_compose<Operation1, Operation2, Operation3>(op1, op2, op3);
}

用于函数指针:ptr_fun。将函数指针转换成仿函数对象,便于和STL中的算法和仿函数进行配合使用,因为单纯的函数指针是无法进行配接的。

template <class Arg, class Result>
class pointer_to_unary_function : public unary_function<Arg, Result> {
protected:
    Result(*ptr)(Arg);
public:
    pointer_to_unary_function() {}
    explicit pointer_to_unary_function(Result(*x)(Arg)) : ptr(x) {}
    Result operator()(Arg x) const { return ptr(x); }
};

// 将一元函数指针转换成一元仿函数对象
template <class Arg, class Result>
inline pointer_to_unary_function<Arg, Result> ptr_fun(Result(*x)(Arg)) {
    return pointer_to_unary_function<Arg, Result>(x);
}

template <class Arg1, class Arg2, class Result>
class pointer_to_binary_function : public binary_function<Arg1, Arg2, Result> {
protected:
    Result(*ptr)(Arg1, Arg2);
public:
    pointer_to_binary_function() {}
    explicit pointer_to_binary_function(Result(*x)(Arg1, Arg2)) : ptr(x) {}
    Result operator()(Arg1 x, Arg2 y) const { return ptr(x, y); }
};

// 将二元函数指针转换成二元仿函数对象
template <class Arg1, class Arg2, class Result>
inline pointer_to_binary_function<Arg1, Arg2, Result>
ptr_fun(Result(*x)(Arg1, Arg2)) {
    return pointer_to_binary_function<Arg1, Arg2, Result>(x);
}

// 使用举例
int add(int a, int b)
{
    return a + b;
}

int main()
{
    auto addFunc = std::ptr_fun(&add);
    std::cout << addFunc(1, 2);

    return 0;
}

用于成员函数指针:mem_fun、mem_fun_ref。作用和ptr_fun类似,不过是用于成员函数。

template <class T>
class mem_fun_t<void, T> : public unary_function<T*, void> {
public:
    explicit mem_fun_t(void (T::*pf)()) : f(pf) {}
    void operator()(T* p) const { (p->*f)(); }             // 使用成员函数指针进行函数调用
private:
    void (T::*f)();
};

template <class S, class T>
inline mem_fun_t<S, T> mem_fun(S(T::*f)()) {
    return mem_fun_t<S, T>(f);
}

template <class S, class T>
class mem_fun_ref_t : public unary_function<T, S> {
public:
    explicit mem_fun_ref_t(S(T::*pf)()) : f(pf) {}
    S operator()(T& r) const { return (r.*f)(); }        // 使用成员函数对引用进行函数调用
private:
    S(T::*f)();
};

template <class S, class T>
inline const_mem_fun_ref_t<S, T> mem_fun_ref(S(T::*f)() const) {
    return const_mem_fun_ref_t<S, T>(f);
}

int main()
{
    std::vector<Example*> vec = {
        &Example(1),
        &Example(2),
        &Example(3),
        &Example(4),
        &Example(5)};
    std::for_each(vec.begin(), vec.end(), std::mem_fun(&Example::printOut));   // 1,2,3,4,5

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值