配接器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;
}