bind1st 和bind2nd
bind1st : operator()的第一个形参变量绑定成一个确定的值
bind2nd : operator()的第二个形参变量绑定成一个确定的值
实例:
将数组从大到小排序后,按顺序插入70
#include <iostream>
#include <vector>
#include <functional>
#include <algorithm>
#include <ctime>
using namespace std;
template<typename Container>
void showContainer(Container& con)
{
typename Container::iterator it = con.begin();
//编译器是从上到下编译的,这个还没有实例化,它不知道这个名字作用域后面的iterator是类型还是变量
//typename告知编译器后面类型的作用域后面是类型
for (; it != con.end(); ++it)
{
cout << *it << " ";
}
cout << endl;
}
int main()
{
vector<int> vec;
srand(time(nullptr));
for (int i = 0; i < 10; ++i)
{
vec.push_back(rand() % 100 + 1);//随机出来的数字,并不是有序的
}
showContainer(vec);
//greater 二元函数对象
sort(vec.begin(), vec.end(), greater<int>());//大到小排序
showContainer(vec);
//把70按顺序插入到vec容器当中,找第一个小于70的数字
auto it1 = find_if(vec.begin(), vec.end(),
bind1st(greater<int>(), 70));
//auto it1 = find_if(vec.begin(), vec.end(),bind2nd(less<int>(), 70));
if (it1 != vec.end())
{
vec.insert(it1, 70);
}
showContainer(vec);
return 0;
}
实现原理
find_if的源码;
// FUNCTION TEMPLATE find_if
template<class _InIt,
class _Pr>
_NODISCARD inline _InIt find_if(_InIt _First, const _InIt _Last, _Pr _Pred)
{ // find first satisfying _Pred
_Adl_verify_range(_First, _Last);
auto _UFirst = _Get_unwrapped(_First);
const auto _ULast = _Get_unwrapped(_Last);
for (; _UFirst != _ULast; ++_UFirst)
{
if (_Pred(*_UFirst))
{
break;
}
}
_Seek_wrapped(_First, _UFirst);
return (_First);
}
其中第三个参数_Pred是一个一元函数对象
bind1st源码
// FUNCTION TEMPLATE bind1st
template<class _Fn,
class _Ty>
_NODISCARD inline binder1st<_Fn> bind1st(const _Fn& _Func, const _Ty& _Left)
{ // return a binder1st functor adapter
typename _Fn::first_argument_type _Val(_Left);
return (binder1st<_Fn>(_Func, _Val));
}
它是一个函数模板,返回一元函数对象binder1st
binder1st
// CLASS TEMPLATE binder1st
template<class _Fn>
class binder1st
: public unary_function<typename _Fn::second_argument_type,
typename _Fn::result_type>
{ // functor adapter _Func(stored, right)
public:
typedef unary_function<typename _Fn::second_argument_type,
typename _Fn::result_type> _Base;
typedef typename _Base::argument_type argument_type;
typedef typename _Base::result_type result_type;
binder1st(const _Fn& _Func,
const typename _Fn::first_argument_type& _Left)
: op(_Func), value(_Left)
{ // construct from functor and left operand
}
result_type operator()(const argument_type& _Right) const
{ // apply functor to operands
return (op(value, _Right));
}
result_type operator()(argument_type& _Right) const
{ // apply functor to operands
return (op(value, _Right));
}
protected:
_Fn op; // the functor to apply
typename _Fn::first_argument_type value; // the left operand
};
一元函数对象默认构造函数接受两个参数, op和 value。赋值运算符接收一个参数,并使用传入的op和vaule 进行运算:op(value, _Right)
简单的实现如下:
#include <iostream>
#include <vector>
#include <functional>
#include <algorithm>
#include <ctime>
using namespace std;
template<typename Container>
void showContainer(Container& con)
{
typename Container::iterator it = con.begin();
for (; it != con.end(); ++it)
{
cout << *it << " ";
}
cout << endl;
}
template<typename Iterator, typename Compare>
Iterator my_find_if(Iterator first, Iterator last, Compare comp)
//遍历这2个迭代器之间的元素,如果满足函数对象的运算,就返回当前迭代器,如果都不满足,返回end()
{
for (; first != last; ++first)
{
if (comp(*first))//comp.operator()(*first)一元函数对象,因为要从容器拿1个元素和它指定的元素比较
//my_find_if需要1元函数对象,而在库里面都是二元的
{
return first;
}
}
return last;
}
template<typename Compare, typename T>
class _mybind1st//绑定器是函数对象的一个应用
{
public:
_mybind1st(Compare comp, T val)
:_comp(comp), _val(val)
{}
bool operator()(const T& second)
{
return _comp(_val, second);//greater
}
private:
Compare _comp;
T _val;
};
//mybind1st(greater<int>(), 70)
template<typename Compare, typename T>
_mybind1st<Compare, T> mybind1st(Compare comp, const T& val)
{
//直接使用函数模板,好处是,可以进行类型的推演
return _mybind1st<Compare, T>(comp, val);
}
int main()
{
vector<int> vec;
srand(time(nullptr));
for (int i = 0; i < 20; ++i)
{
vec.push_back(rand() % 100 + 1);
}
showContainer(vec);
//greater 二元函数对象
sort(vec.begin(), vec.end(), greater<int>());//大到小排序
showContainer(vec);
/*
把70按顺序插入到vec容器当中 找第一个小于70的数字
operator()(const T &val)
greater a > b
less a < b
绑定器 + 二元函数对象 =》 一元函数对象
bind1st: + greater bool operator()(70, const _Ty& _Right)
bind2nd: + less bool operator()(const _Ty& _Left, 70)
*/
auto it1 = my_find_if(vec.begin(), vec.end(),
mybind1st(greater<int>(), 70));
//auto it1 = my_find_if(vec.begin(), vec.end(),bind2nd(less<int>(), 70));
if (it1 != vec.end())
{
vec.insert(it1, 70);
}
showContainer(vec);
return 0;
}
function
解决绑定器,函数对象,lambda表达式只能使用在一条语句中的问题;
定义:传递一个 _Fty function type 希望传递一个函数类型
// CLASS TEMPLATE function
template<class _Fty>
class function
: public _Get_function_impl<_Fty>::type
{ // wrapper for callable objects
private:
typedef typename _Get_function_impl<_Fty>::type _Mybase;
public:
function() noexcept
{ // construct empty function wrapper
}
简单使用:
#include <iostream>
#include <vector>
#include <functional>
#include <algorithm>
#include <ctime>
#include <string>
using namespace std;
void hello1()
{
cout << "hello world!" << endl;
}
void hello2(const string &str)//void (*pfunc)(string)
{
cout << str << endl;
}
int sum(int a, int b)
{
return a + b;
}
class Test
{
public://必须依赖一个对象void (Test::*pfunc)(string)
void hello(string str) { cout << str << endl; }
};
int main()
{
/*
1.用函数类型实例化function
2.通过function调用operator()函数的时候,需要根据函数类型传入相应的参数
*/
//从function的类模板定义处,看到希望用一个函数类型实例化function
function<void()> func1 = hello1;
func1();//func1.operator()() => hello1()
function<void(string)> func2 = hello2;
func2("hello hello2!");//func2.operator()(string str) => hello2(str)
function<int(int, int)> func3 = sum;
cout << func3(20, 30) << endl;
//operator() lambda 表达式
function<int(int, int)> func4 = [](int a, int b)->int {return a + b; };
cout << func4(100, 200) << endl;
//类成员函数
function<void(Test*, string)> func5 = &Test::hello;
func5(&Test(), "call Test::hello!");//临时对象调用
return 0;
}
模板的完全特例化和部分特例化
对于下面的compare,对于char类型的比较不能满足实际的需要,因此对compare特例化一个版本compare<const char *>
#include <iostream>
#include <vector>
#include <functional>
#include <algorithm>
#include <ctime>
#include <string>
using namespace std;
template<typename T>
bool compare(T a, T b)
{
cout << "template compare" << endl;
return a > b;
}
template<>
bool compare<const char*>(const char*a, const char*b)//特例化
{
cout << "compare<const char*>" << endl;
return strcmp(a, b) > 0;
}
int main()
{
compare(10, 20);//
compare("aaa", "bbb");//T const char*
return 0;
}
匹配原则:有完全特例化则先匹配完全特例化,其次部分特例化,最后函数模板
#include <iostream>
#include <vector>
#include <functional>
#include <algorithm>
#include <ctime>
#include <string>
using namespace std;
//类模板
template<typename T>
class Vector
{
public:
Vector() { cout << "call Vector template init" << endl; }
};
//下面这个是对char*类型提供的完全特例化版本(<>中T已知:即下面的char *) #1
template<>//特例化的语法
class Vector<char*>
{
public:
Vector() { cout << "call Vector<char*> init" << endl; }
};
//下面这个是对指针类型提供的部分特例化版本 #2
//仅知道是一个指针,类型需要提供
template<typename Ty>
class Vector<Ty*>
{
public:
Vector() { cout << "call Vector<Ty*> init" << endl; }
};
//指针函数指针(有返回值,有两个形参变量)提供的部分特例化
template<typename R, typename A1, typename A2>
class Vector<R(*)(A1, A2)>
{
public:
Vector() { cout << "call Vector<R(*)(A1, A2)> init" << endl; }
};
//针对函数(有一个返回值,有两个形参变量)类型提供的部分特例化
template<typename R, typename A1, typename A2>
class Vector<R(A1, A2)>
{
public:
Vector() { cout << "call Vector<R(A1, A2)> init" << endl; }
};
int sum(int a, int b) { return a + b; }
int main()
{
Vector<int> vec1;
Vector<char*> vec2;
Vector<int*> vec3;
Vector<int(*)(int, int)> vec4;
Vector<int(int, int)> vec5;//function
//注意区分一下函数类型和函数指针类型
typedef int(*PFUNC1)(int, int);
PFUNC1 pfunc1 = sum;
cout << pfunc1(10, 20) << endl;
typedef int PFUNC2(int, int);
PFUNC2 *pfunc2 = sum;
cout << (*pfunc2)(10, 20) << endl;
return 0;
}
实参推演:
#include <iostream>
#include <typeinfo>
using namespace std;
int sum(int a, int b) { return a + b; }
//T包含了所有的大的类型 返回值,所有形参的类型都取出来
template<typename T>
void func(T a)
{
cout << typeid(T).name() << endl;
}
//细化返回值类型和参数类型
template<typename R, typename A1, typename A2>
void func2(R(*a)(A1, A2))
{
cout << typeid(R).name() << endl;
cout << typeid(A1).name() << endl;
cout << typeid(A2).name() << endl;
}
class Test
{
public:
int sum(int a, int b) { return a + b; }
};
//实参推演每一个类型
template<typename R, typename T, typename A1, typename A2>
void func3(R(T::* a)(A1, A2))
{
cout << typeid(R).name() << endl;
cout << typeid(T).name() << endl;
cout << typeid(A1).name() << endl;
cout << typeid(A2).name() << endl;
}
int main()
{
func(10);
func("aaa");
func(sum);//T int (*)(int,int) int (int,int)
func(&Test::sum);//int (__thiscall Test::*)(int,int)
//
cout << "---------------------func2\n";
func2(sum);
cout << "---------------------func3\n";
func3(&Test::sum);//int (__thiscall Test::*)(int,int)
return 0;
}
function 原理剖析
#include <iostream>
#include <typeinfo>
#include <string>
#include <functional>
using namespace std;
/*
function函数对象类型的实现原理
*/
void hello(string str) { cout << str << endl; }
int sum(int a, int b) { return a + b; }
//定义个函数模板
template<typename Fty>
class myfunction {};
//部分偏特化版本 <R(A1)
template<typename R, typename A1>
class myfunction<R(A1)>
{
public:
using PFUNC = R(*)(A1);
myfunction(PFUNC pfunc) :_pfunc(pfunc) {}
R operator()(A1 arg)
{
return _pfunc(arg);//hello(arg)
}
private:
PFUNC _pfunc;
};
/*
//部分偏特化版本 R(*)(A1, A2);
template<typename R, typename A1, typename A2>
class myfunction<R(A1, A2)>
{
public:
using PFUNC = R(*)(A1, A2);
myfunction(PFUNC pfunc) :_pfunc(pfunc) {}
R operator()(A1 arg1, A2 arg2)
{
return _pfunc(arg1, arg2);//hello(arg)
}
private:
PFUNC _pfunc;
};
*/
//通用版本
template<typename R, typename... A>//一组可变参数个数:表示一组类型
class myfunction<R(A...)>
{
public:
using PFUNC = R(*)(A...);
myfunction(PFUNC pfunc) :_pfunc(pfunc) {}
R operator()(A... arg)//一组形参变量
{
return _pfunc(arg...);//hello(arg) 表示一组形参变量
}
private:
PFUNC _pfunc;
};
int main()
{
myfunction<void(string)> func1(hello);
func1("hello world!");//func1.operator()("hello world!")
myfunction<int(int, int)> func2(sum);
cout << func2(10, 20) << endl;
return 0;
}
fuction 底层是一个可变参的偏特化函数对象
bind
C++11 bind绑定器,是一个函数模板 ,可以自动推演模板类型参数=> 返回的结果还是一个函数对象
bind占位符最多有20个参数
#include <iostream>
#include <typeinfo>
#include <string>
#include <memory>
#include <vector>
#include <functional>
#include <thread>
using namespace std;
using namespace placeholders;
/*
C++11 bind绑定器 => 返回的结果还是一个函数对象
*/
void hello(string str) { cout << str << endl; }
int sum(int a, int b) { return a + b; }
class Test
{
public:
int sum(int a, int b) { return a + b; }
};
int main()
{
//bind是函数模板 可以自动推演模板类型参数
bind(hello, "hello bind!")();//返回的结果是绑定器,也就是函数对象 最后一个()表示调用函数对象的operator()
cout << bind(sum, 10, 20)() << endl;
cout << bind(&Test::sum, Test(), 20, 30)() << endl;
//参数占位符 绑定器出了语句,无法继续使用
//只是占位的作用,调用的时候就要传递参数了
//书写的时候使用多少个占位符,就是意味着用户调用的时候要传入几个参数
bind(hello, placeholders::_1)("hello bind 2!");
cout << bind(sum, placeholders::_1, placeholders::_2)(200, 300) << endl;
//此处把bind返回的绑定器binder就复用起来了
function<void(string)> func1 = bind(hello, _1);
func1("hello china!");
func1("hello shan xi!");
func1("hello si chuan!");
return 0;
}
placeholders 占位符:最多支持20个