C++ STL 内 std::{bind/tuple/function} 简单实现

 更新时间:2020年02月20日 10:15:07   作者:Dosk 技术站  
这篇文章主要介绍了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} 简单实现的文章就介绍到这了,更多相关C++  std::{bind/tuple/function}内容请搜素脚本之家以前的文章或下面相关文章,希望大家以后多多支持脚本之家!

相关文章

  • Eclipse对printf()不能输出到控制台的快速解决方法

    Eclipse对printf()不能输出到控制台的快速解决方法

    Eclipse对printf()不能输出到控制台的快速解决方法。需要的朋友可以过来参考下,希望对大家有所帮助
    2013-10-10
  • C++设计模式之外观模式

    C++设计模式之外观模式

    这篇文章主要介绍了C++设计模式之外观模式,本文详细讲解了C++中的Facade模式,并给出了实例代码,需要的朋友可以参考下
    2014-10-10
  • C/C++中memset,memcpy的使用及fill对数组的操作

    C/C++中memset,memcpy的使用及fill对数组的操作

    这篇文章主要介绍了C/C++中memset,memcpy的使用及fill对数组的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-12-12
  • C++中最常用的容器用法与排序实例

    C++中最常用的容器用法与排序实例

    C++ 中容器被定义为:在数据存储上,有一种对象类型,它可以持有其它对象或指向其它对像的指针,这种对象类型就叫做容器,这篇文章主要给大家介绍了关于C++中最常用的容器用法与排序的相关资料,需要的朋友可以参考下
    2021-08-08
  • C++实现学生选课系统

    C++实现学生选课系统

    这篇文章主要为大家详细介绍了C++实现学生选课系统,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-02-02
  • C/C++获取目录下的文件列表信息

    C/C++获取目录下的文件列表信息

    在C/C++编程时,需要获取目录下面的文件列表信息,下面把代码分享一下
    2014-02-02
  • C语言中的指针新手初阶指南

    C语言中的指针新手初阶指南

    指针是C语言的灵魂,精华之所在,指针强大而危险,用得好是一大利器,用得不好是一大潜在危害,下面这篇文章主要给大家介绍了C语言中指针的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考下
    2021-10-10
  • C++制作俄罗斯方块

    C++制作俄罗斯方块

    俄罗斯方块写过好几次了,每次的感觉都不一样,都有新的收获。就像达芬奇画鸡蛋一样,虽然都是画同样的鸡蛋,但是每次都有不同的收获。&nbsp;
    2016-05-05
  • C语言编写获取Linux本地目录及本机信息的小程序实例

    C语言编写获取Linux本地目录及本机信息的小程序实例

    这篇文章主要介绍了C语言编写获取Linux本地目录及本机信息的小程序实例,小程序能够根据参数输出目录的结构以及获取主机用户的信息,需要的朋友可以参考下
    2016-04-04
  • C++中const的实现机制深入分析

    C++中const的实现机制深入分析

    C语言以及C++语言中的const究竟表示什么?其具体的实现机制又是如何实现的呢?本文将对这两个问题进行一些分析,需要了解的朋友可以参考下
    2012-12-12

最新评论