zoukankan      html  css  js  c++  java
  • 从零开始写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);
    	}
    
    
  • 相关阅读:
    hdu 4849
    HDU4850 构造一个长度为n的串,要求任意长度为4的子串不相同
    2014 多校第一场官方题解。
    hdu4862 2014多校B题/ 费用流(最优情况下用不大于K条路径覆盖)(不同的解法)
    dp+分类讨论 Gym 101128E
    优先队列 逆向思维 Gym 101128C
    很好的脑洞题:dfs+暴力 Gym
    树dp...吧 ZOJ 3949
    扫描线(线段树)+贪心 ZOJ 3953
    dp ZOJ 3956
  • 原文地址:https://www.cnblogs.com/joeylee97/p/8670888.html
Copyright © 2011-2022 走看看