《STL原始碼剖析》筆記-配接器adapters
阿新 • • 發佈:2018-12-19
配接器adapters在STL中起到轉換、連線的作用,包括仿函式配接器(function adapter)、容器配接器(container adapter)、迭代器配接器(iterator adapter)。
容器配接器
迭代器配接器
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;
}