① 先简单看没有类的情况,示例代码如下:
#include <iostream>
void func0() {
std::cout << "no param, no return" << std::endl;
}
void func1(int) {
std::cout << "one param, no return" << std::endl;
}
void func2(int arg1, double arg2) {
std::cout << "two param, no return, arg1: " << arg1 << ", arg2: " << arg2 << std::endl;
}
int func3() {
std::cout << "no param, have return" << std::endl;
return 1;
}
int func4(int) {
std::cout << "one param, have return" << std::endl;
return 2;
}
template<class Func, class ...Args>
auto Call(Func call, Args ...args)
{
return call(args...);
}
int main() {
Call(&func0);
Call(&func1, 1);
Call(&func2, 1, 2.5);
std::cout << "func3 return: " << Call(&func3) << std::endl;
std::cout << "func4 return: " << Call(&func4, 1) << std::endl;
system("pause");
return 0;
}
执行结果如下所示:
函数模板Call函数支持有返回值和无返回值两种,参数是变长的,甚至参数类型可以不一样。
② 如果调用的方法在类里面,这里可以用bind函数将参数绑定起来调用,代码如下:
#include <iostream>
#include <functional>
class Test {
public:
void func0() {
std::cout << "no param, no return" << std::endl;
}
void func1(int) {
std::cout << "one param, no return" << std::endl;
}
void func2(int arg1, double arg2) {
std::cout << "two param, no return, arg1: " << arg1 << ", arg2: " << arg2 << std::endl;
}
int func3() {
std::cout << "no param, have return" << std::endl;
return 1;
}
int func4(int) {
std::cout << "one param, have return" << std::endl;
return 2;
}
};
template<class Func, class ...Args>
auto Call(Func call, Args ...args)
{
return call(args...);
}
int main() {
Test tt;
Call(std::bind(&Test::func0,&tt));
Call(std::bind(&Test::func1,&tt,1));
Call(std::bind(&Test::func2,&tt,1,2.5));
std::cout << "func3 return: " << Call(std::bind(&Test::func3,&tt)) << std::endl;
std::cout << "func4 return: " << Call(std::bind(&Test::func4,&tt,1)) << std::endl;
system("pause");
return 0;
}
输出结果一模一样:
这里main函数里面实际也可以用function替换,代码如下:
std::function<void(void)> f0 = std::bind(&Test::func0, &tt);
std::function<void(int)> f1 = std::bind(&Test::func1, &tt,std::placeholders::_1);
std::function<void(int , double)> f2 = std::bind(&Test::func2, &tt, std::placeholders::_1, std::placeholders::_2);
std::function<int(void)> f3 = std::bind(&Test::func3, &tt);
std::function<int(int)> f4 = std::bind(&Test::func4, &tt, std::placeholders::_1);
f0(), f1(1), f2(1, 2.5);
std::cout << "func3 return: " << f3() << std::endl;
std::cout << "func4 return: " << f4(1) << std::endl;
运行结果是一样的,这里如果用auto替换function,则代码会更简单。
③ 在另外一个类里面存储所有方法并执行,示例代码如下:
#include <vector>
#include <future>
#include <iostream>
#include <functional>
class Test {
public:
void func0() {
std::cout << "no param, no return" << std::endl;
}
void func1(int) {
std::cout << "one param, no return" << std::endl;
}
void func2(int arg1, double arg2) {
std::cout << "two param, no return, arg1: " << arg1 << ", arg2: " << arg2 << std::endl;
}
int func3() {
std::cout << "no param, have return" << std::endl;
return 1;
}
int func4(int) {
std::cout << "one param, have return" << std::endl;
return 2;
}
};
class Bind {
public:
template<class Func, class ...Args>
void Call(Func call, Args ...args) {
auto task = std::bind(call, args...);
m_map.emplace_back([task]() {(task)(); });
}
void Exec() {
for (auto& func : m_map) {
func();
}
}
private:
std::vector<std::function<void()>> m_map;
};
int main() {
Bind bb; Test tt;
bb.Call(std::bind(&Test::func0, &tt));
bb.Call(std::bind(&Test::func1, &tt, 1));
bb.Call(std::bind(&Test::func2, &tt, 1, 2.5));
bb.Call(std::bind(&Test::func3, &tt));
bb.Call(std::bind(&Test::func4, &tt, 1));
bb.Exec();
system("pause");
return 0;
}
运行结果如下:
这里借助了bind函数将函数和参数绑定起来存储(bind函数的返回值就是function类型,而且如果要运行bind的值,只需要在表达式后面加括号即可),如果直接在类中存储模板变量会报错(是否有办法不报错,现在不清楚)。
以上代码如果用上完美转发代码改成如下所示:
class Bind {
public:
template<class Func, class ...Args>
void Call(Func&& call, Args&& ...args) {
auto task = std::bind(std::forward<Func>(call), std::forward<Args>(args)...);
m_map.emplace_back([task]() {(task)(); });
}
void Exec() {
for (auto& func : m_map) {
func();
}
}
private:
std::vector<std::function<void()>> m_map;
};
这里还有一个问题,上面的func3和func4是有返回值的,如何在main中将其打印出来?代码修改如下:
#include <vector>
#include <future>
#include <iostream>
#include <functional>
class Test {
public:
void func0() {
std::cout << "no param, no return" << std::endl;
}
void func1(int) {
std::cout << "one param, no return" << std::endl;
}
void func2(int arg1, double arg2) {
std::cout << "two param, no return, arg1: " << arg1 << ", arg2: " << arg2 << std::endl;
}
int func3() {
std::cout << "no param, have return" << std::endl;
return 1;
}
int func4(int) {
std::cout << "one param, have return" << std::endl;
return 2;
}
};
class Bind {
public:
template<class Func, class ...Args>
auto Call(Func&& call, Args&& ...args) {
using return_type = typename std::result_of<Func(Args...)>::type;
auto task = std::make_shared< std::packaged_task<return_type()> >(
std::bind(std::forward<Func>(call), std::forward<Args>(args)...)
);
std::future<return_type> res = task->get_future();
m_map.emplace_back([task] {(*task)(); });
return res;
}
void Exec() {
for (auto& func : m_map) {
func();
}
}
private:
std::vector<std::function<void()>> m_map;
};
int main() {
Bind bb; Test tt;
bb.Call(std::bind(&Test::func0, &tt));
bb.Call(std::bind(&Test::func1, &tt, 1));
bb.Call(std::bind(&Test::func2, &tt, 1, 2.5));
auto res3 = bb.Call(std::bind(&Test::func3, &tt));
auto res4= bb.Call(std::bind(&Test::func4, &tt, 1));
bb.Exec();
std::cout << "func3 return: " << res3.get()<<std::endl;
std::cout << "func4 return: " << res4.get() << std::endl;
system("pause");
return 0;
}
执行结果如下: