您好,登錄后才能下訂單哦!
這篇文章主要介紹C++ STL內 std::{bind/tuple/function}的使用方法,文中介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們一定要看完!
基本邏輯思考
首先是實現 function,這個比較簡單,重載 operator() 就好,這里只實現對函數指針的包裝
其次是實現 tuple,這個會比較繞,通過模板取第一個參數,然后用剩下的參數繼續生成 tuple并繼承,是一種遞歸的思想
有了 tuple 就要有 get(),這個就更比較繞了,首先是需要類似的方式實現獲得 tuple 的值類型與元組類型,然后通過強制類型轉換,獲取對應的層級的 value
接下來是 bind,首先要解決的就是如何保存創建時的參數列表,這里就用到 tuple 來保存了
奇技淫巧還是運行函數時取相應的元組的對應位置的值,還是類似的方式,通過特化模板,公式是 <n, indexs...> => <n - 1, n - 1, indexs...>,比如 3 最后會生成 0 0 1 2 那么拋棄第一個,并用來展開元組,傳遞給函數指針
最重要的來了,就是如何實現 placeholders,簡單來說就是在上一步的 operator() 增加傳入參數,并制造成元組 r_args,然后帶進一個 _unwrap_tuple 類,這里會重載 operator[] 根據傳入數據結構,如果是 _placeholders<index> 那么取 r_args 相應的 index 位置,否則會直接 return
代碼
不多說,還是直接放代碼,僅作為參考,有寫的不好的地方輕噴
/* * Author: SpringHack - springhack@live.cn * Last modified: 2020-02-19 10:16:17 * Filename: main.cpp * Description: Created by SpringHack using vim automatically. */ #include <iostream> namespace dosk { // begin namespace dosk // function template <typename... T> class function; template <typename Result, typename... Args> class function<Result(Args...)> { private: Result (*function_)(Args...); public: typedef Result return_type; function() = default; function(Result (*fn)(Args...)) : function_(fn) {}; Result operator()(Args... a) { return function_(a...); } function& operator=(Result (*fn)(Args...)) { function_ = fn; return *this; } }; // tuple template <typename... T> class tuple; template <typename HEAD, typename... LIST> class tuple<HEAD, LIST...> : public tuple<LIST...> { public: HEAD value; tuple(HEAD head, LIST... list) : tuple<LIST...>(list...), value(head) {}; }; template <> class tuple<> {}; // tuple get template <int index, typename... T> class _tuple_type; template <int index, typename HEAD, typename... LIST> class _tuple_type<index, tuple<HEAD, LIST...>> { public: typedef typename _tuple_type<index - 1, tuple<LIST...>>::value_type value_type; typedef typename _tuple_type<index - 1, tuple<LIST...>>::tuple_type tuple_type; }; template <typename HEAD, typename... LIST> class _tuple_type<0, tuple<HEAD, LIST...>> { public: typedef HEAD value_type; typedef tuple<HEAD, LIST...> tuple_type; }; template <int index, typename HEAD, typename... LIST> typename _tuple_type<index, tuple<HEAD, LIST...>>::value_type get(tuple<HEAD, LIST...> t) { typedef typename _tuple_type<index, tuple<HEAD, LIST...>>::value_type value_type; typedef typename _tuple_type<index, tuple<HEAD, LIST...>>::tuple_type tuple_type; value_type rv = ((tuple_type)t).value; return rv; } // bind template <size_t...> class _tuple_index {}; template <size_t n, size_t... indexs> class _make_indexs : public _make_indexs<n - 1, n - 1, indexs...> {}; template<size_t... indexs> class _make_indexs<0, indexs...> { public: typedef _tuple_index<indexs...> index_type; }; namespace placeholders { template <size_t index> class _placeholders {}; _placeholders<0> _1; _placeholders<1> _2; _placeholders<2> _3; _placeholders<3> _4; _placeholders<4> _5; _placeholders<5> _6; _placeholders<6> _7; _placeholders<7> _8; _placeholders<8> _9; _placeholders<9> _10; template <typename... RArgs> class _unwrap_tuple { public: tuple<RArgs...> r_args; _unwrap_tuple(tuple<RArgs...> r_args) : r_args(r_args) {}; template <typename R> R operator[](R r) { return r; } template <size_t index> auto operator[](placeholders::_placeholders<index>) { return get<index>(r_args); } }; }; template <typename Func, typename... Args> class bind_t { public: typedef typename _make_indexs<sizeof...(Args)>::index_type _indexs; typedef typename Func::return_type return_type; Func func; tuple<Args...> args; bind_t(Func func, Args... args): func(func), args(args...) {} template <typename... RArgs> return_type operator()(RArgs&&... _r_args) { tuple<RArgs...> r_args = tuple<RArgs...>(_r_args...); return run(_indexs(), r_args); } template <size_t... Idx, typename... RArgs> return_type run(_tuple_index<Idx...>, tuple<RArgs...> r_args) { return func(unwrap_args<Idx>(r_args)...); } template <size_t index, typename... RArgs> auto unwrap_args(tuple<RArgs...> r_args) { placeholders::_unwrap_tuple<RArgs...> _u_a(r_args); auto _m_a = get<index>(args); return _u_a[_m_a]; } }; template <typename Func, typename... Args> bind_t<Func, Args...> bind(Func& func, Args&&... args) { return bind_t<Func, Args...>(func, args...); } }; // end namespace dosk // Test code std::string test_func(int a, const char * b) { return std::to_string(a) + std::string(b); } std::string test_bind_args(int a, int b, int c, int d, int e) { return std::to_string(a) + std::to_string(b) + std::to_string(c) + std::to_string(d) + std::to_string(e); } int main() { // Test tuple dosk::tuple<int, const char *> t(123, "456"); std::cout << dosk::get<0>(t) << dosk::get<1>(t) << std::endl; // Test function dosk::function<std::string(int, const char *)> closure_1 = test_func; std::cout << closure_1(123, "456") << std::endl; // Test bind dosk::function<std::string(int, int, int, int, int)> closure_2 = test_bind_args; auto binder = dosk::bind(closure_2, 1, dosk::placeholders::_2, 3, dosk::placeholders::_1, 5); std::cout << binder(4, 2, 0) << std::endl; return 0; }
以上是“C++ STL內 std::{bind/tuple/function}的使用方法”這篇文章的所有內容,感謝各位的閱讀!希望分享的內容對大家有幫助,更多相關知識,歡迎關注億速云行業資訊頻道!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。