系列文章目录
模板特例化,偏特化,左右值引用 https://blog.csdn.net/surfaceyan/article/details/126794013
C++ STL 关联容器 https://blog.csdn.net/surfaceyan/article/details/127414434
C++ STL 序列式容器(二) https://blog.csdn.net/surfaceyan/article/details/127083966
C++ STL 序列式容器(一) https://blog.csdn.net/surfaceyan/article/details/126860166
C++STL迭代器iterator设计 https://blog.csdn.net/surfaceyan/article/details/126772555
C++11 标准库头文件模拟实现,无锁STL https://blog.csdn.net/surfaceyan/article/details/126772555
文章目录
- 系列文章目录
- 前言
- 概念分类
- 容器适配器
- 迭代器适配器
- 1. insert iterators
- 2. reverse iterators
- 3. stream iterators
- function adapters
- 4. 用于函数指针:ptr_fun
- 5. 用于成员函数指针: mem_fun, mem_fun_ref
- 总结
前言
适配器(adapters)在STL组件的灵活组合运用上扮演者重要角色。Adapter这个概念源于23个设计模式中的一个:将一个class的接口转换为以一个class接口,使原本因接口不兼容而不能合作的classes可以一起运作。
实际上就是在原有的接口上再套一层接口
或许叫接口适配器或者接口层也可
概念分类
改变函数对象接口的称为function adapter,改变容器接口的称为 container adapter, 改变迭代器接口的称为 iterator adapter。
queue和stack就是容器适配器。
容器适配器和迭代器适配器
#include <iterator>
#include <deque>
#include <algorithm>
#include <iostream>
using namespace std;
int main(int argc, char* argv[])
{
ostream_iterator<int> outite(cout, " ");
int ia[] = {0,1,2,3,4,5};
deque<int> id(ia, ia+6);
copy(id.begin(), id.end(), outite);
cout << endl;
copy(ia+1, ia+2, front_inserter(id));
copy(ia+3, ia+4, back_inserter(id));
copy(id.begin(), id.end(), outite);
cout << endl;
deque<int>::iterator ite = find(id.begin(), id.end(), 5);
copy(ia+0, ia+3, inserter(id, ite));
copy(id.begin(), id.end(), outite);
cout << endl;
copy(id.rbegin(), id.rend(), outite);
cout << endl;
istream_iterator<int> inite(cin), eos; // end-of-stream
copy(inite, eos, inserter(id, id.begin()));
copy(id.begin(), id.end(), outite);
cout << endl;
}
应用于函数的适配器
所有期望获取适配能力的组件,本事必须是可适配的,也就是说,一元仿函数必须继承自 unary_function,二元仿函数必须继承自 binary_function ,成员函数必须以mem_fun处理过,一般函数必须以 ptr_fun 处理过,一个未经ptr_fun处理的一般函数,虽然也可以函数指针的形式传递STL算法使用,却无法有任何适配能力
void print(int i)
{
cout << i << ' ';
}
class Int
{
private:
int m_i;
public:
explicit Int(int i) : m_i(i) {}
~Int() {}
void print1() const
{
cout << '[' << m_i << ']';
}
};
template<class Arg, class Result>
struct unary_function
{
typedef Arg argument_type;
typedef Result result_type;
};
template <class Arg1, class Arg2, class Result>
struct binary_function
{
typedef Arg1 first_argument_type;
typedef Arg2 second_argument_type;
typedef Result result_type;
};
stringstream scout;
ostream_iterator<int> outite(scout, " ");
int ia[6] = {2, 21, 12, 7, 19, 23};
vector<int> iv(ia, ia+6);
cout << count_if(iv.begin(), iv.end(), [](int a)->bool {return a>=12;});
cout << endl;
transform(iv.begin(), iv.end(), outite, [](int a)->int {return (a+2)*3;});
cout << scout.str() << endl;
copy(iv.begin(), iv.end(), outite);
cout << scout.str() << endl;
for_each(iv.begin(), iv.end(), print);
cout << endl;
for_each(iv.begin(), iv.end(), ptr_fun(print));
cout << endl;
for_each(iv.begin(), iv.end(), bind(print, placeholders::_1));
cout << endl;
Int t1(3), t2(7), t3(20), t4(14), t5(68);
vector<Int> Iv;
Iv.push_back(t1);
Iv.push_back(t2);
Iv.push_back(t3);
Iv.push_back(t4);
Iv.push_back(t5);
for_each(Iv.begin(), Iv.end(), mem_fun_ref(&Int::print1)); // 私有成员函数必须用指针
cout << endl;
for_each(Iv.begin(), Iv.end(), bind(&Int::print1, placeholders::_1));
cout << endl;
其中std::bind是更易于使用更通用的方法,用它!
容器适配器
template<typename T, typename Sequence = deque<T>>
class stack{
protected:
Sequence c;
...
};
迭代器适配器
由用户指定一个容器,在调用 迭代器适配器 时调用指定容器的对应方法
1. insert iterators
可细分为back insert iterator, front insert iterator和insert iterator,分别将对应类型的“指针解引用并赋值”(*p = value)操作修改为对应容器的方法
template<class Container>
class back_insert_iterator
{
protected:
Container* container;
public:
typedef std::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& operator=(const typename Container::value_type& value)
{
container->push_back(value);
return *this;
}
back_insert_iterator& operator*() {return *this;}
back_insert_iterator& operator++() {return *this;}
back_insert_iterator& operator++(int) {return *this;}
};
template <class Container>
class front_insert_iterator
{
protected:
Container* container;
public:
typedef std::output_iterator_tag iterator_category;
typedef void value_type;
typedef void difference_type;
typedef void pointer;
typedef void reference;
explicit front_insert_iterator(Container& c) : container(&c) {}
front_insert_iterator& operator=(const typename Container::value_type& v)
{
container->push_front(v);
return *this;
}
front_insert_iterator& operator*() {return *this;}
front_insert_iterator& operator++() {return *this;}
front_insert_iterator& operator++(int) {return *this;}
};
template <class Container>
class insert_iterator
{
protected:
Container* container;
typename Container::iterator iter;
public:
typedef std::output_iterator_tag iterator_category;
typedef void value_type;
typedef void difference_type;
typedef void pointer;
typedef void reference;
explicit insert_iterator(Container& c, typename Container::iterator i) : container(&c), iter(i) {}
insert_iterator& operator=(const typename Container::value_type& v)
{
iter = container->insert(iter, v);
++iter;
return *this;
}
insert_iterator& operator*() {return *this;}
insert_iterator& operator++() {return *this;}
insert_iterator& 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>
inline front_insert_iterator<Container> front_inserter(Container& x)
{
return front_insert_iterator<Container>(x);
}
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::deque<int> v{1,2,3};
auto bins = ::front_inserter(v);
*bins = 4;
*bins = 6;
std::ostream_iterator<int> outite(std::cout, " ");
std::copy(v.begin(), v.end(), outite); std::cout << std::endl;
}
2. reverse iterators
和reverse_iterator迭代器相关,将移动操作倒转
copy(v.rbegin(), v.rend(), ite)看似简单,实则暗藏玄机
typedef reverse_iterator<iterator> reverse_iterator;
reverse_iterator rbegin() {return reverse_iterator(end());}
reverse_iterator rend() {return reverse_iterator(begin());}
template <class Iterator>
class reverse_iterator
{
protected:
Iterator current; // 记录对应之正向迭代器
public:
typedef typename std::iterator_traits<Iterator>::iterator_category iterator_category;
typedef typename std::iterator_traits<Iterator>::value_type value_type;
typedef typename std::iterator_traits<Iterator>::difference_type difference_type;
typedef typename std::iterator_traits<Iterator>::pointer pointer;
typedef typename std::iterator_traits<Iterator>::reference reference;
typedef Iterator iterator_type;
typedef reverse_iterator<Iterator> self;
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; // key point
}
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;
}
difference_type operator-(const self& second) const
{
return second.current - current;
}
reference operator[](difference_type n) const
{
return *(*this+n);
}
};
int main()
{
std::deque<int> v{1,2,3};
::reverse_iterator<std::deque<int>::iterator> rbegin(v.end()), rend(v.begin());
std::ostream_iterator<int> outite(std::cout, " ");
// copy到outite迭代器所指的位置
std::copy(rbegin, rend, outite); std::cout << std::endl;
}
3. stream iterators
就是将迭代器绑定到一个stream对象身上。绑定到istream(std::cin)身上叫istream_iterator,拥有输入能力;绑定到ostream(std::cout)身上的叫ostream_iterator, 拥有输出能力。
所谓绑定是指,在iterator内部维护一个stream成员,客户端对该iterator的所有操作都转换成该stream成员的操作。
template <typename T, typename Distance = std::ptrdiff_t>
class istream_iterator
{
friend bool operator==(const istream_iterator<T, Distance>& x, const istream_iterator<T, Distance>& y);
protected:
std::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 std::input_iterator_tag iterator_category;
typedef T value_type;
typedef Distance difference_type;
typedef const T* pointer;
typedef const T& reference;
istream_iterator() : stream(&std::cin), end_marker(false) {}
explicit istream_iterator(std::istream& s) : stream(&s) { read(); }
reference operator*() const { return value; }
pointer operator->() const { return &(operator*()); }
istream_iterator& operator++()
{
read();
return *this;
}
istream_iterator operator++(int)
{
istream_iterator<T, Distance> tmp = *this;
read();
return tmp;
}
};
template <typename T>
class ostream_iterator
{
protected:
std::ostream* stream;
const char* string;
public:
typedef std::output_iterator_tag iterator_category;
typedef void value_type;
typedef void difference_type;
typedef void pointer;
typedef void reference;
explicit ostream_iterator(std::ostream& s) : stream(&s), string(0) {}
ostream_iterator(std::ostream& s, const char* c) : stream(&s), string(c) {}
ostream_iterator operator=(const T& value)
{
*stream << value;
if (string) *stream << string;
return *this;
}
ostream_iterator& operator*() {return *this;}
ostream_iterator& operator++() {return *this;}
ostream_iterator& operator++(int) {return *this;}
};
以上两个迭代器在应用上非常重要,说明了如何为自己量身定制一个迭代器。可以完成一个绑定到 Internet Explorer 身上的迭代器,也可以完成一个绑定到磁盘目录上的迭代器······
function adapters
std::bind
4. 用于函数指针:ptr_fun
@deprecated Deprecated in C++11, no longer in the standard since C++17.
5. 用于成员函数指针: mem_fun, mem_fun_ref
@deprecated Deprecated in C++11, no longer in the standard since C++17. Use
mem_fn instead.
std::mem_fn
总结
algorithm里存放各种算法如accumulate,sort等
functional里存各种xx函数如std::move, less, greater等
适配器一般要和泛型算法配合使用方可体现其强大之处