C++标准库 STL —— 仿函数和适配器
Posted 张三和李四的家
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++标准库 STL —— 仿函数和适配器相关的知识,希望对你有一定的参考价值。
仿函数
function call operator 仿函数中的 函数名,是一个 operator()
仿函数主要是用来服务算法的,如果要被算法调用就需要重载 ()
。这里称这种()
为 function call operator
仿函数主要分为三大类:
-
算术类
template <class T> struct plus : public binary_function<T, T, T> T operator()(const T& x, const T & y) const return x + y; ;
-
逻辑运算类
template <class T> struct logical_and: public binary_function<T, T, bool> bool operator()(const T& x, const T& y) const return x && y;
-
相对关系类
template <class T> struct equal_to : public binary_function<T, T, bool> bool operator()(const T& x, const T& y) const return x == y;
算法使用仿函数的场景
template<typename Iterator, typename Cmp>
Algorithm(Iterator itr1, Iterator itr2, Cmp Comp)
//cmp 即仿函数
为什么需要继承 binary_function?
template <class Arg1, class Arg2, class Reuslt>
struct binary_function
typedef Arg1 first_argument_type;
typedef Arg2 second_argument_type;
typedef Result result_type;
;
通过继承 binay_function ,仿函数获取到了一些typedef,而这些typedef 会被适配器所需要。
Adapter
容器适配器:用于改造容器
stack,queue 都内含了一个 deque,stack,queue 的功能都是由 deque 实现的,所有stack,queue 是 deque 的容器适配器。
仿函数适配器:用于改造仿函数
仿函数的可适配条件
STL 提供每个 Adaptable Function 都应挑选适当者继承(因为Function Adapter 将会提问)。例如:
templdate<class Arg1, classs Arg2, class Result>
struct binary_function
typedef Arg1 Frist_argument_type;
typedef Arg2 second_argument_type;
typedef Result result_type;
;
templdate <class T>
struct less : public binary_function<T, T, bool>
bool operator()(const T& x, const T& y) const
return x < y;
;
上面是仿函数以及基类定义。
这些在 仿函数适配器中会被用到。
bind2nd(less<int>(), 40);//typename+() == 产生一个临时对象,less<int>()就是一个仿函数对象
template <class T> less<int T> //本来是用来比大小(x < y)的,被bing2nd 修饰了之后,函数功能发生了变化。
//现在函数的功能为 (x < 40)
怎么实现的呢?
template <class _Operation, class _Tp>
inline binder2nd<_Operation> //返回的是什么
bind2nd(const _Operation& __oper, const _Tp& __x)
typedef typename _Operation::second_argument_type _Arg2_type;//关于这里的typename的作用
/*
编译器在编译到 _Operator 时,但它还没有被使用,不知道是什么?只有在传入参数的时候才知道。所以编译器就犹豫这行代码是否会被编译通过。而typename 就告诉编译器,typename 后面的 是一个类型。需要被编译通过。
*/
return binder2nd<_Operation>(__oper, _Arg2_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;//记下第二参数 需要是 _Operation::second_argument_type 类型
public:
binder2nd(const _Operation& __x,
const typename _Operation::second_argument_type& __y)
: op(__x), value(__y)
// _Operation::result_type 按照原函数中的返回类型,进行返回
typename _Operation::result_type
operator()(const typename _Operation::first_argument_type& __x) const
return op(__x, value); //调用函数并返回
;
typename
- 在模板声明的模板参数列表中,可以使用typename代替类 来声明类型模板参数
- 在模板的声明和定义中
typename
可用于声明从属限定名称为一个类型(防止编译器报错或警告)。
例如上面的typedef typename _Operation::second_argument_type _Arg2_type;
新型适配器
std::bind 绑定函数,可以绑定下面 object
- functions
- function objects
- member functions,
_1
必须是某个 object 地址 - data members,
_1
必须是某个object 地址
这个函数呢,会返回一个 function object ret
。调用ret
相当于调用上述1, 2, 3, 或相当于取出4
绑定函数
auto fn_five = bind(my_divide, 10,2);
cout << fn_five() << '\\n';
上面截图显示了,bind 函数的函数签名。
绑定数据成员
struct Foo
int a, b;
;
Foo pair1,2;
auto memdata = bind(&Foo::a, pair);
cout << memdata() << endl;
下面展示和算法和混用
vector<int> v 51,52,40,20,70,20,59;
auto fn = bind(less<int>(), _1, 50);
cout << count_if(v.cbegin(), v.cend(), fn) << endl;
cout << count_if(v.begin(), v.end(), bind(less<int>(), _1, 50)) << endl;
cout << count_if(v.cbegin(), v.cend(), bind2nd(less<int>(), 50)) << endl;
迭代器适配器:用于改造迭代器
tuple
template <typename... Values> class tuple;
template<> class tuple<>;
template <typename Head, typename... Tail>
class tuple<Head, Tail...>
:private tuple<Tail...>
typedef tuple<Tail...> inherited;
public:
tuple()
tuple(Head v, Tail... vtail)
: m_head(v), inherited(vtail...)
typename Head::type head() return m_head;
inherited& tail() return *this;//return 后,转型为 inherited ,实际获得的是 Tail...
protected:
Head m_head;
;
tuple 一种类似于 pair 的集合型容器类。可以将不同类似的对象包装到一起。应该是可以包含无限的对象。
实现方式:通过递归继承来实现。
Traits
traits 获取对象的类型。
实现格式: 模板的泛化和特化
template <typename _Tp>
struct remove_const
typedef _Tp type;
;
template <typename _Tp>
struct remove_const<const _Tp>
typedef _Tp type;
;
template <typename _Tp>
struct remove_volatile
typedef _Tp type;
;
template <typename _Tp>
struct remove_volatile<volatile _Tp>
typedef _Tp type;
;
/*
* 将传入的`const volatile Type` 去掉 const 和 volatile ,还原原始的类型
*/
template <typename _Tp>
struct remove_cv
typedef typename remove_const<typename remove_volatile<_Tp>::type>::type type;
;
template<typename>
struct __is_void_helper
:public false_type;
template<typename>
struct __is_void_helper<void>:
public true_type;
template <typename _Tp>
struct is_void :
public __is_void_helper<typename remove_cv<_Tp>::type>::type ;
cout
cout 是一个类吗?不,它是一个对象。因为你不能直接拿一个类来使用。
以上是关于C++标准库 STL —— 仿函数和适配器的主要内容,如果未能解决你的问题,请参考以下文章