一、简介
为STL组件提供更加灵活的用法,可应用于函数、容器、迭代器;
二、容器配接器
stack,是在deque容器进行封装;
queue,是在deque上进行封装;
三、迭代器配接器
- insert iterators:插入迭代器,提供尾插、首插、以及任意位置插入的方法;
- reverse iterators:将正向的迭代器逆转;
- iostream iterators:将迭代器绑定到iostream上;
- ostream_iterator:输出;
- istream_iterator:输入;
insert Iterator
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;
explicit insert_iterator(Container& x, typename Container::iterator i) : container(&x), iter(i) {}
insert_iterator<Container>&
operator=(const typename Container::value_type& value) {
container->insert(iter, value);
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> iterator(Container& x, Iterator i) {
return insert_iterator<Container> (x, iter(i));
}
back 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) {}
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_insert(Container& x) {
return back_insert_iterator<Container> (x);
}
front insert_iterator
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) {}
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_iterator(Container& x) {
return front_insert_iterator<Container> (x);
}
reverse iterator
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 *this;
}
self operator+(difference_type n) const {
return self(current-n);
}
self& operator+=(difference_type n) const {
current -= n;
return *this;
}
self operator-(difference_type n) const {
return self(current + n);
}
self& operator-=(difference_type n) const {
current += n;
return *this;
}
reference operator[](difference_type n) const { return *(*this + n); }
};
istream iterator
template<class T, class Distance = ptrdiff_t>
class istream_iterator {
template<>
friend bool operator==(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;
end_marker = (*stream) ? true : false;
}
public:
typedef intput_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;
}
};
ostream iteraotr
template<class T>
class ostream_iterator {
protected:
ostream* stream;
const char* string;
public:
typedef ontput_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) { }
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; }
};
四、函数配接器
能给函数提供绑定、组合、修饰能力;
【注意】:会改变参数的和不改变参数的不能搭配使用;
1、自定义函数如何才能有配接能力
若为一元仿函数则必须继承unarg_funtion,二元需要继承binary_function,成员函数必须与mem_fun处理;
成员函数配接器:mem_fun_ref
template <class S, class T>
mem_fun_ref_t<S,T> mem_fun_ref (S (T::*f)())
{ return mem_fun_ref_t<S,T>(f); }
func:将成员函数转换为函数对象,引用版本,`mem_fun`为指针版;
eg:
for_each(arr.begin(), end.begin(), mem_fun_ref(&Func::pprint));
即调用Func中的const成员函数pprint,打印arr的所有元素;
==> 若需要传入参数,可使用bind2nd进行绑定传参;
【为什么使用配接器进行函数传参?】
> 使用配接器能够将`原本针对某个元素的函数调用动作`转为`调用被传递的成员函数`;
非成员函数配接器:ptr_fun
template <class Arg, class Result>
pointer_to_unary_function<Arg,Result> ptr_fun (Result (*f)(Arg));
template <class Arg1, class Arg2, class Result>
pointer_to_binary_function<Arg1,Arg2,Result> ptr_fun (Result (*f)(Arg1,Arg2));
func:将函数指针转换为函数对象;
- 当时用的仿函数需要提供特殊的型别;
- 当使用一个双参数全局函数,想当做单参数使用,并结合bind2nd;
void print(int i) {
cout << i << " ";
}
class Int{
public:
int m_i;
Int(int i) : m_i(i) {}
void print() const { cout << "[" << m_i << "]"; }
};
void test_men_fun() {
ostream_iterator<int> outite(cout, " ");
vector<int> vc = {1, 3, 7, 8, 10};
for_each(vc.begin(), vc.end(), ptr_fun(print));
cout << endl;
Int t1(3), t2(7), t3(20);
vector<Int> vvc = { t1, t2, t3 };
for_each(vvc.begin(), vvc.end(), mem_fun_ref(&Int::print));
}
2、函数绑定
函数绑定:bind2nd
template <class Operation, class T>
binder2nd<Operation> bind2nd (const Operation& op, const T& x);
func:绑定第二参数;
eg:
find_if(arr.begin(), arr.end(), bind2nd(less<int>(), 4));
即查找arr中【<=4】的数;
函数绑定:bind1st
template <class Operation, class T>
binder1st<Operation> bind1st (const Operation& op, const T& x);
func:绑定第一参数;
函数绑定:bind
template <class Fn, class... Args>
bind (Fn&& fn, Args&&... args);
template <class Ret, class Fn, class... Args>
bind (Fn&& fn, Args&&... args);
func:C++11后提供,提供的模板可接受多种参数,也可接受返回值类型类型;
通过使用占位符对函数参数进行传递;在std::placeholders下;
【注意】:_1即第一参数,_2即第二参数,和位置没有关系;
void test_bind() {
using namespace std::placeholders;
vector<int> vc{1, 4, 6, 7, 8};
int num = count_if(vc.begin(), vc.end(), binder1st(less<int>(), 4));
cout << "4<=x num: " << num << endl;
num = count_if(vc.begin(), vc.end(), binder2nd(less<int>(), 4));
cout << "x<=4 num: " << num << endl;
auto fn = bind(less<int>(), _1, 4);
num = count_if(vc.begin(), vc.end(), fn);
cout << "x<=4 num: " << num << endl;
auto fn_1 = bind([](int x, int y){ return x < y; }, _1, 10);
cout << "20 < 10: " << (fn_1(20) ? "y": "n") << endl;
auto fn_2 = bind([](int x, int y){ return x < y; }, _2, _1);
cout << "20 < 10: " << (fn_2(20, 10) ? "y": "n") << endl;
}
3、辅助配接器
将其中的函数运算结果作为另一个函数的参数输入 ;
#include <iostream>
#include <functional>
#include <iterator>
#include <algorithm>
#include <vector>
using namespace std;
template<class T1, class T2>
class compose_f_gx_t : public std::unary_function<typename T2::argument_type,
typename T1::result_type>{
private:
T1 op1;
T2 op2;
public:
compose_f_gx_t(const T1& o1, const T2& o2)
:op1(o1), op2(o2) {
}
typename T1::result_type
operator()(const typename T2::argument_type& x) const {
return op1(op2(x));
}
};
template<class T1, class T2>
inline compose_f_gx_t<T1, T2>
compose_f_gx(const T1& o1, const T2& o2) {
return compose_f_gx_t<T1, T2>(o1, o2);
}
void test() {
std::vector<int> vc;
for(int i=0; i<9; ++i) {
vc.push_back(i);
}
transform(vc.begin(), vc.end(),
ostream_iterator<int>(cout, " "),
compose_f_gx(bind2nd(multiplies<int>(), 5),
bind2nd(plus<int>(), 10)));
std::cout << std::endl;
}
int main(int argc, char* argv[])
{
test();
return 0;
}
|