function C++11 将任意类型的可调用(Callable)对象与函数调用的特征封装到一起。

这里的类是对函数策略的封装,将函数的性质抽象成组件,便于和algorithm库配合使用

基本运算符 和 基本比较符号组件

	template<class Arg, class Result>
struct unary_function
{
typedef Arg argument_type;
typedef Result result_type;
}; template<class Arg1, class Arg2, class Result>
struct binary_function
{
typedef Arg1 first_argument_type;
typedef Arg2 second_argument_type;
typedef Result result_type;
}; template<class T>
struct plus : binary_function<T, T, T>
{
T operator()(const T& x, const T& y) const
{
return x + y;
}
}; template<class T>
struct minus :binary_function<T, T, T>
{
T operator()(const T& x, const T& y) const
{
return x - y;
}
}; template<class T>
struct multiplies : binary_function<T, T, T>
{
T operator()(const T& x, const T& y) const
{
return x*y;
}
}; template <class T>
struct modulus : binary_function <T, T, T>
{
T operator() (const T& x, const T& y) const
{
return x%y;
}
}; template<class T>
struct negate :unary_function<T, T>
{
T operator()(const T& x) const
{
return -x;
}
}; template<class T>
struct less :binary_function<T, T, bool>
{
bool operator()(const T&lhs, const T& rhs) const
{
return lhs < rhs;
}
}; template <class T>
struct greater : binary_function<T, T, bool>
{
bool operator()(const T& lhs, const T& rhs) const
{
return lhs > rhs;
}
}; template <class T>
struct equal_to : binary_function <T, T, bool>
{
bool operator() (const T& x, const T& y) const
{
return x == y;
}
}; template<class T>
struct greater_equal : binary_function<T, T, bool>
{
bool operator()(const T& lhs, const T& rhs)
{
return lhs >= rhs;
}
}; template<class T>
struct less_equal : binary_function<T, T, bool>
{
bool operator()(const T& lhs, const T& rhs)
{
return lhs <= rhs;
}
};

逻辑运算组件

对已经封装好的函数组件的运行结果增加一层封装。

	template <class Predicate>
class unary_negate
: public unary_function <typename Predicate::argument_type, bool>//参数类型是传入Predicate的参数类型,返回类型为bool
{
protected:
Predicate fn;
public:
explicit unary_negate(const Predicate& pred) : fn(pred) {}
bool operator() (const typename Predicate::argument_type& x) const
{
return !fn(x);
}
}; template <class Predicate>
class binary_negate
: public binary_function<typename Predicate::first_argument_type, typename Predicate::second_argument_type, bool>
{
protected:
Predicate fn;
public:
explicit binary_negate(const Predicate& pred) :fn(pred) {}
bool operator() (const typename Predicate::first_argument_type& x,
const typename Predicate::second_argument_type& y) const
{
return !fn(x, y);
}
};

参数绑定

将要调用的参数保存在结构中,调用的时候再传入

使用typename 和 模板 来指明返回类型 和 参数类型

建议使用explicit来避免隐式类型转换

	template<class Operation>
class binder1st
: public binary_function<typename Operation::first_argument_type, typename Operation::second_argument_type, typename Operation::result_type>
{
protected:
typename Operation::first_argument_type val;//要绑定的参数
Operation op;
public:
explicit binder1st(const Operation& operation, const typename Operation::first_argument_type x) :op(operation),val(x) {}
typename Operation::result_type operator()(const typename Operation::second_argument_type& xs)
{
return op(val, x);
}
}; //绑定第二个参数
template<class Operation>
class binder2nd
: public binary_function<typename Operation::first_argument_type, typename Operation::second_argument_type, typename Operation::result_type>
{
protected:
typename Operation::second_argument_type val;
Operation op;
public:
explicit binder2nd(const Operation& operation, const typename Operation::second_argument_type x) :op(operation),val(x) {}
typename Operation::result_type operator()(const typename Operation::first_argument_type& xs)
{
return op(x, val);
}
};

不定参数的绑定

底层数据 结构用tuple来实现,对于调用参数的获取,维护一个tuple index 模板类,去在模板中递归生成对应下标,这一部分涉及大量的模板元编程。

  • 为什么要生成所有参数的下标?

    需要知道参数的位置,顺序,这样对应着进行模板展开,从tuple中get出对应位置的参数传入函数进行调用
  • 如何生成?

    模板展开 + 模板偏特化
	template <std::size_t...>
struct tuple_indices {}; //生成下标 注意第二个模板是一个类模板 , 第一和第三个模板参数作为展开的边界
template <std::size_t Sp, class IntTuple, std::size_t Ep>
struct make_indices_imp; template <std::size_t Sp, std::size_t... Indices, std::size_t Ep>
struct make_indices_imp<Sp, tuple_indices<Indices...>, Ep>
{
typedef typename make_indices_imp<Sp + 1, tuple_indices<Indices..., Sp>, Ep>::type type;
}; //对结束位置进行特化
template <std::size_t Ep, std::size_t... Indices>
struct make_indices_imp<Ep, tuple_indices<Indices...>, Ep>
{
typedef tuple_indices<Indices...> type;
}; template <std::size_t Ep, std::size_t Sp = 0>
struct make_tuple_indices
{
typedef typename make_indices_imp<Sp, tuple_indices<>, Ep>::type type;
};

具体tuple的内部实现改天再写。。。

	//绑定不定数目 不定类型的参数
//底层数据通过tuple来保存实现
要实现
template <class F, class... Args>
struct binder
{
//使用std::forward 进行完美转发
//可见 http://en.cppreference.com/w/cpp/utility/forward
binder(F&& f, Args&&... args) :data(std::forward<F>(f), std::forward<Args>(args)...) {}
inline auto operator()()
{
typedef typename make_tuple_indices<std::tuple_size<std::tuple<F, Args...> >::value, 1>::type index_type;
return run2(index_type());
}
template <std::size_t... Indices>
void run2(tuple_indices<Indices...>)
{
//模板展开
invoke(std::move(std::get<0>(data)), std::move(std::get<Indices>(data))...);
}
inline auto invoke(F&& f, Args&&... args)
{
//f 作为函数指针 ,args 作为参数传入
return std::forward<F>(f)(std::forward<Args>(args)...);
}
//使用tuple来保存数据
std::tuple<F,Args...> data;
}; template <class F, class... Args >
ministl::binder<F,Args...> bind(F&& f, Args&&... args)
{
return binder<F, Args...>(std::forward<F>(f), std::forward<Args>(args)...);
}

对类成员函数进行调用

大部分可以用lambda 代替,不过还是写一下,不作重点,精髓还是在于bind

template <class S, class T> mem_fun_t<S, T> mem_fun(S(T::*f)())
{
return mem_fun_t<S, T>(f);
} template <class S, class T, class A>
class mem_fun1_t : public binary_function <T*, A, S>
{
S(T::*pmem)(A);
public:
explicit mem_fun1_t(S(T::*p)(A)) : pmem(p) {}
S operator() (T* p, A x) const
{
return (p->*pmem)(x);
}
}; template <class S, class T, class A> mem_fun1_t<S, T, A> mem_fun(S(T::*f)(A))
{
return mem_fun1_t<S, T, A>(f);
} template <class S, class T>
class const_mem_fun_t : public unary_function <T*, S>
{
S(T::*pmem)() const;
public:
explicit const_mem_fun_t(S(T::*p)() const) : pmem(p) {}
S operator() (T* p) const
{
return (p->*pmem)();
}
}; template <class S, class T> const_mem_fun_t<S, T> mem_fun(S(T::*f)() const)
{
return const_mem_fun_t<S, T>(f);
} template <class S, class T, class A>
class const_mem_fun1_t : public binary_function <T*, A, S>
{
S(T::*pmem)(A) const;
public:
explicit const_mem_fun1_t(S(T::*p)(A) const) : pmem(p) {}
S operator() (T* p, A x) const
{
return (p->*pmem)(x);
}
}; template <class S, class T, class A> const_mem_fun1_t<S, T, A> mem_fun(S(T::*f)(A) const)
{
return const_mem_fun1_t<S, T, A>(f);
} template <class S, class T>
class mem_fun_ref_t : public unary_function <T, S>
{
S(T::*pmem)();
public:
explicit mem_fun_ref_t(S(T::*p)()) : pmem(p) {}
S operator() (T& p) const
{
return (p.*pmem)();
}
};
template<class S,class T,class A>
class mem_fun1_ref_t : public binary_function<T, S, A>
{
S(T::*pmem)(A);
public:
explicit mem_fun1_ref_t(S(T::*p)(A)) :pmem(p) {}
S operator()(T& p, A x) const
{
return (p.*pmem)(x);
}
}; template <class S, class T>
class const_mem_fun_ref_t : public unary_function <T, S>
{
S(T::*pmem)() const;
public:
explicit const_mem_fun_ref_t(S(T::*p)() const) : pmem(p) {}
S operator() (T& p) const
{
return (p.*pmem)();
}
}; template <class S, class T, class A>
class const_mem_fun1_ref_t : public binary_function <T, A, S>
{
S(T::*pmem)(A) const;
public:
explicit const_mem_fun1_ref_t(S(T::*p)(A) const) : pmem(p) {}
S operator() (T& p, A x) const
{
return (p.*pmem)(x);
}
}; //Returns a function object that encapsulates member function f of type T.
template <class S, class T>
mem_fun_ref_t<S, T> mem_fun_ref(S(T::*f)())
{
return mem_fun_ref_t<S, T>(f);
} template <class S, class T, class A>
mem_fun1_ref_t<S, T, A> mem_fun_ref(S(T::*f)(A))
{
return mem_fun1_ref_t<S, T, A>(f);
} template <class S, class T>
const_mem_fun_ref_t<S, T> mem_fun_ref(S(T::*f)() const)
{
return const_mem_fun_ref_t<S, T>(f);
} template <class S, class T, class A>
const_mem_fun1_ref_t<S, T, A> mem_fun_ref(S(T::*f)(A) const)
{
return const_mem_fun1_ref_t<S, T, A>(f);
}

从零开始写STL—functional的更多相关文章

  1. 从零开始写STL - 智能指针

    从零开始写STL - 智能指针 智能指针的分类及其特点: scoped_ptr:初始化获得资源控制权,在作用域结束释放资源 shared_ptr: 引用计数来控制共享资源,最后一个资源的引用被释放的时 ...

  2. 从零开始写STL—栈和队列

    从零开始写STL-栈和队列 适配器模式 意图:将一个类的接口转换成客户希望的另外一个接口.适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作. 主要解决:主要解决在软件系统中,常常要将 ...

  3. 从零开始写STL—容器—vector

    从0开始写STL-容器-vector vector又称为动态数组,那么动态体现在哪里?vector和一般的数组又有什么区别?vector中各个函数的实现原理是怎样的,我们怎样使用会更高效? 以上内容我 ...

  4. 从零开始写STL—模板元编程之any

    any class any; (since C++17) The class any describes a type-safe container for single values of any ...

  5. 从零开始写STL—哈希表

    static const int _stl_num_primes = 28; template<typename T, typename Hash = xhash<T>> cl ...

  6. 从零开始写STL—模板元编程之tuple

    tuple Class template std::tuple is a fixed-size collection of heterogeneous values. It is a generali ...

  7. 从零开始写STL—set/map

    这一部分只要把搜索树中暴露的接口封装一下,做一些改动. set源码剖析 template<typename T> class set { public: typedef T key_typ ...

  8. 从零开始写STL-内存部分-内存分配器allocator

    从零开始写STL-内存部分-内存分配器allocator 内存分配器是什么? 一般而言,c++的内存分配和释放是这样操作的 >>class Foo{ //...}; >>Foo ...

  9. 从零开始写STL-容器-list

    从零开始写STL-容器-list List 是STL 中的链表容器,今天我们将通过阅读和实现list源码来解决一下问题: List内部的内存结构是如何实现的? 为什么List的插入复杂度为O(1)? ...

随机推荐

  1. BottomNavigationBar底部导航条用法

    先来张效果图 接下来是实现过程 1.加入依赖 compile 'com.ashokvarma.android:bottom-navigation-bar:1.3.0' 2.xml布局 fragment ...

  2. NSString 与NSMutableString的区别

      NSString 与NSMutableString的区别    Suppose You have a code like this NSString *s = [[NSString alloc]  ...

  3. knockout Observable Array(监控数组)

    Observable Array(监控数组)的作用 列表操作是经常会遇到的一个场景,使用监控数组,你可以: 保存列表对象,并且使用Ko提供的丰富的API操作列表元素(支持内建js Array的方法,以 ...

  4. 解决python pip安装提示"not a supported wheel on this platform"

    python下载.whl安装文件后使用pip安装有时候会提示报错"xxxxx not a supported wheel on this platform",应该是下载的库文件版本 ...

  5. java生成饼图svg

    package com.tellhow.svg; import java.io.File;import java.io.FileOutputStream; /** *  * @author 风絮NO. ...

  6. aaaaa

    svn://192.168.199.182/anti-counterfeiting/trunk svn://192.168.199.182/anti-ds/trunk/antifake-service ...

  7. 微信公众号:theTree20181123

    哈哈哈哈~我开通了一个微信公众号,以后的文章会发在公众号内啦~走过路过的小伙伴们过来围观一下呀~~ 主要是分为三个模块:视觉SLAM,ACM,变美树洞 这里面写下来的文章都是我再读研阶段的所学所想当然 ...

  8. postman使用--断言

    前戏 在我们测接口的时候,没有断言的接口都是耍流氓,因为做自动化的时候,不加断言我们不知道这个接口是执行成功了还是执行失败了,所以断言是做接口自动化必须的 断言 断言就是我们预期值和接口返回值是否一样 ...

  9. python interview questions

    referce:python interview questions top 50 refercence:python interview questions top 15 summary Q: wh ...

  10. cc.Component

    组件入口函数1: onLoad: 组件加载的时候调用, 保证了你可以获取到场景中的其他节点,以及节点关联的资源数据;2: start: 也就是第一次执行 update 之前触发;3: update(d ...