c++ function和bind
阿新 • • 發佈:2019-01-03
1+n fault ref args all main tor bound cal 所替換
bind
定義在頭文件 functional 裏
template<typename _Func, typename... _BoundArgs> inline typename _Bind_helper<__is_socketlike<_Func>::value, _Func, _BoundArgs...>::type bind(_Func&& __f, _BoundArgs&&... __args) template<typename _Result, typename _Func, typename... _BoundArgs> inline typename _Bindres_helper<_Result, _Func, _BoundArgs...>::type bind(_Func&& __f, _BoundArgs&&... __args)
函數模板 bind
生成 f
的轉發調用包裝器。調用此包裝器等價於以一些綁定到 args
的參數調用 f
。類似於 python 的 functools.partial
參數 f 表示可調用對象(函數對象、指向函數指針、函數的引用、指向成員函數指針或指向數據成員指針)
參數 __args 表示要綁定的參數列表。未綁定參數使用命名空間 std::placeholders
的占位符 _1, _2, _3...
需要註意的是:
調用指向非靜態成員函數指針或指向非靜態數據成員指針時,首參數必須是引用或指針(可以包含智能指針,如 std::shared_ptr 與 std::unique_ptr),指向將訪問其成員的對象。
到 bind 的參數被復制或移動,而且決不按引用傳遞,除非包裝於 ref 或 cref
允許同一 bind 表達式中的多重占位符(例如多個 _1
),但結果僅若對應參數( u1
)是左值或不可移動右值才良好定義。
#include <random> #include <iostream> #include <memory> #include<functional> void f(int n1, int n2, int n3, const int& n4, int n5) { std::cout << n1 << ‘ ‘ << n2 << ‘ ‘ << n3 << ‘ ‘ << n4 << ‘ ‘ << n5 << ‘\n‘; } int g(int n1) { return n1; } struct Foo { void print_sum(int n1, int n2) { std::cout << n1+n2 << ‘\n‘; } int data = 10; }; int main() { using namespace std::placeholders; // 對於 _1, _2, _3... // 演示參數重排序和按引用傳遞 int n = 7; // ( _1 與 _2 來自 std::placeholders ,並表示將來會傳遞給 f1 的參數) auto f1 = std::bind(f, _2, _1, 42, std::cref(n), n); n = 10; f1(1, 2, 1001); // 1 為 _1 所綁定, 2 為 _2 所綁定,不使用 1001 // 進行到 f(2, 1, 42, n, 7) 的調用 // 嵌套 bind 子表達式共享占位符 auto f2 = std::bind(f, _3, std::bind(g, _3), _3, 4, 5); f2(10, 11, 12); // 進行到 f(12, g(12), 12, 4, 5); 的調用 // 常見使用情況:以分布綁定 RNG std::default_random_engine e; std::uniform_int_distribution<> d(0, 10); std::function<int()> rnd = std::bind(d, e); // e 的一個副本存儲於 rnd for(int n=0; n<10; ++n) std::cout << rnd() << ‘ ‘; std::cout << ‘\n‘; // 綁定指向成員函數指針 Foo foo; auto f3 = std::bind(&Foo::print_sum, &foo, 95, _1); f3(5); // 100 // 綁定指向數據成員指針 auto f4 = std::bind(&Foo::data, _1); std::cout << f4(foo) << ‘\n‘; // 10 // 智能指針亦能用於調用被引用對象的成員 std::cout << f4(std::make_shared<Foo>(foo)) << ‘\n‘; // 10 return 0; }
function
定義在頭文件 functional 裏
template<typename _Res, typename... _ArgTypes>
class function<_Res(_ArgTypes...)>
類模板 std::function
是通用多態函數封裝器。 std::function
的實例能存儲、復制及調用任何可回調目標——函數、lambda表達式、bind表達式、其他函數對象,還可以指向成員函數指針和指向數據成員指針。
存儲的可調用對象被稱為 std::function
的目標。若 std::function
不含目標,則稱它為空。調用空 std::function
的目標導致拋出 bad_function_call 異常。
function 滿足可復制構造和可復制賦值。
#include <functional> #include <iostream> struct Foo { Foo(int num) : num_(num) {} void print_add(int i) const { std::cout << num_+i << ‘\n‘; } int num_; }; void print_num(int i) { std::cout << i << ‘\n‘; } struct PrintNum { void operator()(int i) const { std::cout << i << ‘\n‘; } }; int main() { // 存儲自由函數 std::function<void(int)> f_display = print_num; f_display(-9); // -9 // 存儲 lambda std::function<void()> f_display_42 = []() { print_num(42); }; f_display_42(); // 42 // 存儲到 std::bind 調用的結果 std::function<void()> f_display_31337 = std::bind(print_num, 31337); f_display_31337(); // 31337 // 存儲到成員函數的調用 std::function<void(const Foo&, int)> f_add_display = &Foo::print_add; const Foo foo(314159); f_add_display(foo, 1); // 314160 f_add_display(314159, 1); // 314160 // 存儲到數據成員訪問器的調用 std::function<int(Foo const&)> f_num = &Foo::num_; std::cout << "num_: " << f_num(foo) << ‘\n‘; // 314159 // 存儲到成員函數及對象的調用 using std::placeholders::_1; std::function<void(int)> f_add_display2 = std::bind( &Foo::print_add, foo, _1 ); f_add_display2(2); // 314161 // 存儲到成員函數和對象指針的調用 std::function<void(int)> f_add_display3 = std::bind( &Foo::print_add, &foo, _1 ); f_add_display3(3); // 314162 // 存儲到函數對象的調用 std::function<void(int)> f_display_obj = PrintNum(); f_display_obj(18); // 18 }
c++ function和bind