《C++11新特性之std::function》提到了std::function作為回調函數。
今天主要討論不同情況下std::function作為回調使用。
**使用回調**
~~~
#include <functional>
#include <iostream>
namespace {
using cb1_t = std::function<void()>;
using cb2_t = std::function<void(int)>;
void foo1()
{
std::cout << "foo1 is called\n";
}
void foo2(int i)
{
std::cout << "foo2 is called with: " << i << "\n";
}
struct S {
void foo3()
{
std::cout << "foo3 is called.\n";
}
};
}
int main()
{
// Bind a free function.
cb1_t f1 = std::bind(&foo1);
// Invoke the function foo1.
f1();
// Bind a free function with an int argument.
// Note that the argument can be specified with bind directly.
cb1_t f2 = std::bind(&foo2, 5);
// Invoke the function foo2.
f2();
// Bind a function with a placeholder.
cb2_t f3 = std::bind(&foo2, std::placeholders::_1);
// Invoke the function with an argument.
f3(42);
// Bind a member function.
S s;
cb1_t f4 = std::bind(&S::foo3, &s);
// Invoke the method foo3.
f4();
// Bind a lambda.
cb1_t f5 = std::bind([] { std::cout << "lambda is called\n"; });
f5();
return 0;
}
~~~
**存儲回調**?
使用回調是非常好的,但是更多的情況下,我們往往需要存儲一些回調函數,并稍后使用。例如,注冊一個客戶端到某個事件上。(也許注冊和事件是C Sharp的詞匯)
我們經常使用std::vector來完成任務。?
缺點就是,我們不能再vector中存儲不同的類型 。?
但是,大多數情況下,一種類型就可以滿足我們了。
~~~
#include <vector>
#include <functional>
#include <iostream>
namespace {
using cb1_t = std::function<void()>;
using callbacks_t = std::vector<cb1_t>;
callbacks_t callbacks;
void foo1()
{
std::cout << "foo1 is called\n";
}
void foo2(int i)
{
std::cout << "foo2 is called with: " << i << "\n";
}
} // end anonymous namespace
int main()
{
// Bind a free function.
cb1_t f1 = std::bind(&foo1);
callbacks.push_back(f1);
// Bind a free function with an int argument.
// Here the argument is statically known.
cb1_t f2 = std::bind(&foo2, 5);
callbacks.push_back(f2);
// Bind a free function with an int argument.
// Here the argument is bound and can be changed at runtime.
int n = 15;
cb1_t f3 = std::bind(&foo2, std::cref(n));
callbacks.push_back(f3);
// Invoke the functions
for(auto& fun : callbacks) {
fun();
}
return 0;
}
~~~
**包裝函數**?
上面提到都不是重點,個人覺得特別重要的就是std::function作為函數的參數使用。?
下面一個例子就將展示一個函數被copy不同的參數。
Note that we always produce an std::function, even though in some cases we could invoke the target directly. Whether this is required depends on the use case. If all the function does is invoking the target, then directly doing it is more efficient. The reason is that std::function does have some overhead, because it is a polymorphic class.
~~~
#include <functional>
#include <iostream>
namespace {
using cb1_t = std::function<void()>;
using cb2_t = std::function<void(int)>;
// Wrapper function with std::function without arguments.
template<typename R>
void call(std::function<R(void)> f)
{
f();
}
// Wrapper function with std::function with arguments.
template<typename R, typename ...A>
void call(std::function<R(A...)> f, A... args)
{
f(args...);
}
// Wrapper function for generic callable object without arguments.
// Delegates to the std::function call.
template<typename R>
void call(R f(void))
{
call(std::function<R(void)>(f));
}
// Wrapper function for generic callable object with arguments.
// Delegates to the std::function call.
template<typename R, typename ...A>
void call(R f(A...), A... args)
{
call(std::function<R(A...)>(f), args...);
}
// Wrapper for a function pointer (e.g. a lambda without capture) without
// arguments.
using fp = void (*)(void);
void call(fp f)
{
call(std::function<void()>(f));
}
void foo1()
{
std::cout << "foo1 is called\n";
}
void foo2(int i)
{
std::cout << "foo2 is called with: " << i << "\n";
}
} // end anonymous namespace
int main()
{
// Call function 1.
call(&foo1);
// Alternative to call function 1.
cb1_t f1 = std::bind(&foo1);
call(f1);
// Call function 2.
call(&foo2, 5);
// Alternative to call function 2.
cb2_t f2 = std::bind(&foo2, std::placeholders::_1);
call(f2, 5);
// Here is an example with a lambda. It calls the function that takes a
// function pointer.
call([] { std::cout << "lambda called\n"; });
return 0;
}
~~~
- 前言
- 吐血整理C++11新特性
- C++11新特性之std::function
- c++11特性之正則表達式
- c++11特性之Lambda表達式
- c++11特性之override和final關鍵字
- c++11特性之std::thread--初識
- c++11特性之std::thread--初識二
- c++11特性之initializer_list
- c++11特性之std::thread--進階
- c++11特性之std::thread--進階二
- C++11新特性之 CALLBACKS
- C++11新特性之 std::array container
- C++11新特性之 nullptr
- C++11新特性之 rvalue Reference(右值引用)
- C++11新特性之 Move semantics(移動語義)
- C++11新特性之 default and delete specifiers
- C++11新特性之 Static assertions 和constructor delegation
- 開始使用C++11的幾個理由
- C++11新特性之 std::future and std::async