从零开始写STL—functional

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);
	}

原文地址:https://www.cnblogs.com/joeylee97/p/8670888.html