万能可调用对象绑定器CPBind

背景

作为一个C++程序员,经常喜欢写一些代码小工具,有一天写代码用到了std::bind,需要和std::function配合使用,并且需要传递的参数类型也已经固定,所以我就想能不能写一个类让它可以接受任意类型的可调用对象(C函数,成员函数,静态函数,lambda表达式,重载operator()的类对象等),所以写出来这个CPBind类达成我想要的效果。

思路

在使用C++14 标准的std::any的时候,浅研究了一下std::any的实现原理,瞬间有了大致思路。使用嵌套类模板可以达到想要的效果。这是最核心的思想之一。

 区别与bind

  1. std::bind功能更强大,功能更丰富。CPBind缺少类似_1,_2,...的按位置绑定,目前仅支持顺序绑定。
  2. 假设两个函数A(std::function<int(int,int)> func), B(CPBind bind)。 那么A接受的可调用对象类型已经固定,即使使用std::bind,类型还是必须需要包括int,int两个参数和返回值为int。而B则没有限制,可以接受任意类型的函数。这是最重要的一个区别,也是为什么要写这个CPBind的原因。
  3. std::bind绑定的时候,也就是在编辑代码的时候,绑定错误就可以立马发现并修改代码。CPBind在绑定的时候发现不了,调用时剩余参数少传入,调用时剩余参数类型传入错误,这些错误只有运行起来的时候才可以发现。
  4.  关于第三点的问题后续慢慢看能不能有什么方案来解决。

 删除了的部分

1.  每一个CPBind对象可以动态的获取绑定的可调用对象的返回值类型,参数类型,可以按照位置获取每一个参数的类型。

2. 类似std::sequencestd::make_sequence的模板类。有标准的我还写个🏀啊!!!


 完整代码

#ifndef CP_UNIVERSAL_H
#define CP_UNIVERSAL_H
#include <memory>
#include <string>
#include <type_traits>
#include <functional>

// 是否启用C++17
#if __cplusplus >= 201703L
#define CPP_HAS_17 1
#endif
namespace CallBack{
// Error id
constexpr int error_id_0_Unclear				= 0;
constexpr int error_id_1_too_few_parameters		= 1;
constexpr int error_id_2_too_many_parameters	= 2;

static const char* error_buffer[]
{
	"Unknown exception. Please carefully check whether the number of parameter bindings or the types of parameter bindings are correct. Note that the type of the incoming parameters needs to strictly correspond.",
	"Too few parameters are passed in",
	"Too many parameters are passed in"
};

class ICallBackException : public std::exception {
public:
	ICallBackException(int error_id = 0)
	{
		m_error_id = error_id;
	}

	virtual const char* what()const override
	{
		return error_buffer[m_error_id];
	}

private:
	int m_error_id{ 0 };
};

class CallBackExceptionUnClear : public ICallBackException
{
public:
	CallBackExceptionUnClear()
		:ICallBackException(error_id_0_Unclear)
	{

	}
};

class CallBackExceptionFewParameters : public ICallBackException
{
public:
	CallBackExceptionFewParameters()
		:ICallBackException(error_id_1_too_few_parameters)
	{

	}
};

class CallBackExceptionManyParameters : public ICallBackException
{
public:
	CallBackExceptionManyParameters()
		:ICallBackException(error_id_2_too_many_parameters)
	{

	}
};

template<typename T> struct Array { using type = T*; };
template<typename T> struct Array<T*> { using type = T(*)[1]; };
template<> struct Array<void*> { using type = void**; };
template<typename T> struct Array<T[]> { using type = T(*)[1]; };

template<typename T> struct function_traits;
template<typename R, typename ...Args>
struct function_traits<R(Args...)>
{
	enum
	{
		arity = sizeof...(Args)
	};
	// static const  char* typeinfos[arity + 1];// 用于元数据获取
	typedef R Ret;
	typedef R function(Args...); 
	typedef R(*function_pointer)(Args...);
	using args_tuple_pointer = std::tuple<typename Array<std::remove_cv_t<std::remove_reference_t<Args>>>::type...>;
};

template<typename args_tuple_pointer, size_t ...I>
struct SGetTuple { using type = std::tuple<std::tuple_element_t<I, args_tuple_pointer>...>; };

//template<typename R, typename ...Args> const  char* function_traits<R(Args...)>::typeinfos[arity + 1] = { nullptr, typeid(Args).name()... };

template<typename R, typename ...Args> struct function_traits<R(*)(Args...)> : public function_traits<R(Args...)>{};
template<typename R, typename ...Args> struct function_traits<std::function<R(Args...)>> : public function_traits<R(Args...)>{};
template<typename R, typename Type, typename ...Args> struct function_traits<R(Type::*)(Args...)> : public function_traits<R(Args...)> { using object = Type; using object_pointer = Type*; };
template<typename R, typename Type, typename ...Args> struct function_traits<R(Type::*)(Args...)const> : public function_traits<R(Args...)> { using object = Type; using object_pointer = Type*; };
template<typename R, typename Type, typename ...Args> struct function_traits<R(Type::*)(Args...)volatile> : public function_traits<R(Args...)> { using object = Type; using object_pointer = Type*; };
template<typename R, typename Type, typename ...Args> struct function_traits<R(Type::*)(Args...)const volatile> : public function_traits<R(Args...)> { using object = Type; using object_pointer = Type*; };
template<class Callable> struct function_traits : public function_traits<decltype(&Callable::operator())> { using object = Callable; };

class Object final
{
public:
	Object()
	{
		data_.reset(nullptr);
	}
	
	template <typename T>
	Object(T* data)
	{
		data_.reset(new ObjectTemplat<T>(data));
	}

	template <typename T>
	Object(const T&data)
	{
		data_.reset(new ObjectTemplat<T>(data));
	}

	Object(const Object&lfvalue)
	{
		data_.swap(const_cast<Object&>(lfvalue).data_);
	}

	Object(Object&&rvalue) noexcept
	{
		data_.swap(const_cast<Object&>(rvalue).data_);
	}

	Object&operator=(const Object&lfvalue) noexcept
	{
		data_.swap(const_cast<Object&>(lfvalue).data_);
		return*this;
	}

	Object&operator=(Object&&rvalue) noexcept
	{
		data_.swap(const_cast<Object&>(rvalue).data_);
		return*this;
	}

	template <typename T>
	T* Cast()
	{
		ObjectTemplat<T>* vptr = dynamic_cast<ObjectTemplat<T>*>(data_.get());
		if (vptr != nullptr)
		{
			return vptr->Get();
		}
		return nullptr;
	}

	template <typename T>
	T& Ref(bool* convert = nullptr)
	{
		ObjectTemplat<T>* vptr = dynamic_cast<ObjectTemplat<T>*>(data_.get());
		if (vptr != nullptr)
		{
			if (convert)
			{
				*convert = true;
			}
		}
		return*vptr->Get();
	}

	template <typename T>
	const T& CRef(bool* convert = nullptr)
	{
		ObjectTemplat<T>* vptr = dynamic_cast<ObjectTemplat<T>*>(data_.get());
		if (vptr != nullptr)
		{
			if (convert)
			{
				*convert = true;
			}
		}
		return*vptr->Get();
	}
protected:
	class IBaseVlaue
	{
	public:
		virtual ~IBaseVlaue() = default;
	};

	template <typename T> class ObjectTemplat : public IBaseVlaue
	{
	public: 
		ObjectTemplat(const T&data)
			: isHeap(true)
		{
#ifdef CPP_HAS_17
			if constexpr (std::is_void_v<T>)
			{
				data_ = data;
			}
			else
			{
#endif
				data_ = new T(data);
#ifdef CPP_HAS_17
			}
#endif
		}

		ObjectTemplat(const T* data)
			: isHeap(true)
		{
				data_ = const_cast<T*>(data);
		}

		ObjectTemplat(T* data, bool isHeap)
			: isHeap(isHeap), data_(isHeap)
		{

		}

		~ObjectTemplat()
		{
			if (isHeap && data_)
			{
				delete data_;
			}
			data_ = nullptr;
		}

		T* Get()
		{
			return data_;
		}
	private:
		bool isHeap;
		T* data_;
	};

	template <> class ObjectTemplat<void> : public IBaseVlaue
	{
	public:
		ObjectTemplat(void* data)
			: isHeap(true)
		{
			data_ = data;
		}

		ObjectTemplat(void* data, bool isHeap)
			: isHeap(isHeap), data_(data)
		{

		}

		~ObjectTemplat()
		{
			if (isHeap && data_)
			{
				::free(data_);
			}
			data_ = nullptr;
		}

		void* Get()
		{
			return data_;
		}
	private:
		bool isHeap;
		void* data_;
	};

private:
	std::unique_ptr<IBaseVlaue> data_;
};

class CPBind
{
public:
	template <typename Function, typename... BindArgs>
	CPBind(const Function&func, BindArgs&&...bindArgs)
	{
		pBinder.reset(new CPFunction<Function, BindArgs...>(func, std::forward<BindArgs&&>(bindArgs)...));
	}
	template <typename R, typename... Args, typename... BindArgs>
	CPBind(R(* Call)(Args...), BindArgs&&...bindArgs)
	{
		pBinder.reset(new CPFunction<R(*)(Args...), BindArgs...>(Call, std::forward<BindArgs&&>(bindArgs)...));
	}
	template <typename R, typename Cla, typename... Args, typename... BindArgs>
	CPBind(R(Cla::* Call)(Args...), Cla* obj, BindArgs&&...bindArgs)
	{
		pBinder.reset(new CPFunction<R(Cla::*)(Args...), BindArgs...>(Call, obj, std::forward<BindArgs&&>(bindArgs)...));
	}
	template <typename R, typename Cla, typename... Args, typename... BindArgs>
	CPBind(R(Cla::* Call)(Args...) const, Cla* obj, BindArgs&&...bindArgs)
	{
		pBinder.reset(new CPFunction<R(Cla::*)(Args...) const, BindArgs...>(Call, obj, std::forward<BindArgs&&>(bindArgs)...));
	}
	template <typename R, typename Cla, typename... Args, typename... BindArgs>
	CPBind(R(Cla::* Call)(Args...) volatile, Cla* obj, BindArgs&&...bindArgs)
	{
		pBinder.reset(new CPFunction<R(Cla::*)(Args...) volatile, BindArgs...>(Call, obj, std::forward<BindArgs&&>(bindArgs)...));
	}
	template <typename R, typename Cla, typename... Args, typename... BindArgs>
	CPBind(R(Cla::* Call)(Args...) const volatile, Cla* obj, BindArgs&&...bindArgs)
	{
		pBinder.reset(new CPFunction<R(Cla::*)(Args...) const volatile, BindArgs...>(Call, obj, std::forward<BindArgs&&>(bindArgs)...));
	}
	CPBind(CPBind&& ot) noexcept
	{
		pBinder.swap(ot.pBinder);
	}
	CPBind& operator=(CPBind&& ot) noexcept
	{
		pBinder.swap(ot.pBinder);
		return*this;
	}
	CPBind& operator=(const CPBind& ot) noexcept
	{
		pBinder.swap(const_cast<std::unique_ptr<IBinderTemplate>&>(ot.pBinder));
		return*this;
	}
	CPBind(const CPBind& ot)
	{
		pBinder.swap(const_cast<std::unique_ptr<IBinderTemplate>&>(ot.pBinder));
	}
	template <typename... Args>
	Object operator()(Args&&... args) const& noexcept
	{
		auto& args_tuple = std::make_tuple(std::addressof(args)...);
		return pBinder->Call(&args_tuple, sizeof...(Args));
	}
	operator bool()
	{
		return pBinder.get() != nullptr;
	}

protected:
	class IBinderTemplate
	{
	public:
		virtual Object Call(void* args, int count) = 0;
		void check(int all, int bind, int in)
		{
			if (all > in + bind)
			{
				throw CallBackExceptionFewParameters();
			}
			else if(all < in +  bind)
			{
				throw CallBackExceptionManyParameters();
			}
			else
			{
			}
		}
		virtual ~IBinderTemplate()
		{
		}

#ifdef CPP_HAS_17
		template<typename RS, typename Function, typename Caller, size_t ...I, size_t ...II, typename ...BindArgs>
		Object CallBack(void* args, Caller& caller, std::tuple<BindArgs...>& bindArgs, const std::index_sequence<I...>&, const std::index_sequence<II...>&)
		{
			using tupleArgs = typename SGetTuple<typename function_traits<Function>::args_tuple_pointer, (II + sizeof...(BindArgs))...>::type;
			tupleArgs& tuple = *reinterpret_cast<tupleArgs*>(args);

			if constexpr (std::is_void_v<RS>)
			{
				caller(std::get<I>(bindArgs)..., *std::get<II>(tuple)...);
				return Object();
			}
			else
			{
				return caller(std::get<I>(bindArgs)..., *std::get<II>(tuple)...);
			}
		}
		
		template<typename RS, typename Function, typename Caller, typename Cla, size_t ...I, size_t ...II, typename ...BindArgs>
		Object CallBack(void* args, Cla* obj, Caller& caller, std::tuple<BindArgs...>& bindArgs, const std::index_sequence<I...>&, const std::index_sequence<II...>&)
		{
			using tupleArgs = typename SGetTuple<typename function_traits<Function>::args_tuple_pointer, (II + sizeof...(BindArgs))...>::type;
			tupleArgs& tuple = *reinterpret_cast<tupleArgs*>(args);

			if constexpr (std::is_void_v<RS>)
			{
				(obj->*caller)(std::get<I>(bindArgs)..., *std::get<II>(tuple)...);
				return Object();
			}
			else
			{
				return (obj->*caller)(std::get<I>(bindArgs)..., *std::get<II>(tuple)...);
			}
		}
	};

#else
		// 使用C++17 constexper if: 代码量减半
		template<typename RS, typename Function, typename Caller, size_t ...I, size_t ...II, typename ...BindArgs>
		Object CallBack(RS*&, void* args, Caller& caller, std::tuple<BindArgs...>& bindArgs, const std::index_sequence<I...>&, const std::index_sequence<II...>&)
		{
			using tupleArgs = typename SGetTuple<typename function_traits<Function>::args_tuple_pointer, (II + sizeof...(BindArgs))...>::type;
			tupleArgs& tuple = *reinterpret_cast<tupleArgs*>(args);
			return caller(std::get<I>(bindArgs)..., *std::get<II>(tuple)...);
		}

		template<typename RS, typename Function, typename Caller, size_t ...I, size_t ...II, typename ...BindArgs>
		Object CallBack(void*&, void* args, Caller& caller, std::tuple<BindArgs...>& bindArgs, const std::index_sequence<I...>&, const std::index_sequence<II...>&)
		{
			using tupleArgs = typename SGetTuple<typename function_traits<Function>::args_tuple_pointer, (II + sizeof...(BindArgs))...>::type;
			tupleArgs& tuple = *reinterpret_cast<tupleArgs*>(args);
			caller(std::get<I>(bindArgs)..., *std::get<II>(tuple)...);
			return Object();
		}

		template<typename RS, typename Function, typename Caller, typename Cla, size_t ...I, size_t ...II, typename ...BindArgs>
		Object CallBack(RS*&, void* args, Cla* obj, Caller& caller, std::tuple<BindArgs...>& bindArgs, const std::index_sequence<I...>&, const std::index_sequence<II...>&)
		{
			using tupleArgs = typename SGetTuple<typename function_traits<Function>::args_tuple_pointer, (II + sizeof...(BindArgs))...>::type;
			tupleArgs tuple1;
			tupleArgs& tuple = *reinterpret_cast<tupleArgs*>(args);
			return (obj->*caller)(std::get<I>(bindArgs)..., *std::get<II>(tuple)...);
		}

		template<typename RS, typename Function, typename Caller, typename Cla, size_t ...I, size_t ...II, typename ...BindArgs>
		Object CallBack(void*&, void* args, Cla* obj, Caller& caller, std::tuple<BindArgs...>& bindArgs, const std::index_sequence<I...>&, const std::index_sequence<II...>&)
		{
			using tupleArgs = typename SGetTuple<typename function_traits<Function>::args_tuple_pointer, (II + sizeof...(BindArgs))...>::type;
			tupleArgs& tuple = *reinterpret_cast<tupleArgs*>(args);
			(obj->*caller)(std::get<I>(bindArgs)..., *std::get<II>(tuple)...);
			return Object();
		}
	};

#endif

	template <typename CallAble, typename... BindArgs>
	class CPFunction : public IBinderTemplate
	{
		using Function = typename function_traits<decltype(&CallAble::operator())>::function;
	public:
		CPFunction(const CallAble& func, BindArgs&&...bindArgs)
			: mCall(func), bindArgs(std::forward<BindArgs&&>(bindArgs)...), bindCount(sizeof...(BindArgs))
		{
		}

		virtual Object Call(void* args, int count) override
		{
			check(function_traits<Function>::arity, sizeof...(BindArgs), count);
			using Ret = typename function_traits<Function>::Ret;
#ifdef CPP_HAS_17
			return CallBack<Ret, Function, CallAble>(args, mCall, bindArgs, std::make_index_sequence<sizeof...(BindArgs)>(), std::make_index_sequence<function_traits<Function>::arity - sizeof...(BindArgs)>());
#else
			Ret* temp = 0;
			return CallBack<Ret, Function, CallAble>(temp, args, mCall, bindArgs, std::make_index_sequence<sizeof...(BindArgs)>(), std::make_index_sequence<function_traits<Function>::arity - sizeof...(BindArgs)>());
#endif
		}

	private:
		const int bindCount;
		CallAble mCall;
		std::tuple<BindArgs...> bindArgs;
	};

	template <typename R, typename... Args, typename... BindArgs>
	class CPFunction<R(*)(Args...), BindArgs...> : public IBinderTemplate
	{
		using Function = R(*)(Args...);
	public:
		CPFunction(Function func, BindArgs&&...bindArgs)
			: mCall(std::forward<Function&&>(func)), bindArgs(std::forward<BindArgs&&>(bindArgs)...), bindCount(sizeof...(BindArgs))
		{
		}

		virtual Object Call(void* args, int count) override
		{
			check(function_traits<Function>::arity, sizeof...(BindArgs), count);
			using Ret = typename function_traits<Function>::Ret;
#ifdef CPP_HAS_17
			return CallBack<Ret, Function, Function>(args, mCall, bindArgs, std::make_index_sequence<sizeof...(BindArgs)>(), std::make_index_sequence<function_traits<Function>::arity - sizeof...(BindArgs)>());
#else
			Ret* temp = 0;
			return CallBack<Ret, Function, Function>(temp, args, mCall, bindArgs, std::make_index_sequence<sizeof...(BindArgs)>(), std::make_index_sequence<function_traits<Function>::arity - sizeof...(BindArgs)>());
#endif
		}

	private:
		const int bindCount;
		Function mCall;
		std::tuple<BindArgs...> bindArgs;
	};

	template <typename R, typename... Args, typename... BindArgs>
	class CPFunction<std::function<R(Args...)>, BindArgs...> : public IBinderTemplate
	{
		using Function = std::function<R(Args...)>;
	public:
		CPFunction(const Function& func, BindArgs&&...bindArgs)
			: mCall(func), bindArgs(std::forward<BindArgs&&>(bindArgs)...), bindCount(sizeof...(BindArgs))
		{
		}

		virtual Object Call(void* args, int count) override
		{
			check(function_traits<Function>::arity, sizeof...(BindArgs), count);
			using Ret = typename function_traits<Function>::Ret;
#ifdef CPP_HAS_17
			return CallBack<Ret, Function, Function>(args, mCall, bindArgs, std::make_index_sequence<sizeof...(BindArgs)>(), std::make_index_sequence<function_traits<Function>::arity - sizeof...(BindArgs)>());
#else
			Ret* temp = 0;
			return CallBack<Ret, Function, Function>(temp, args, mCall, bindArgs, std::make_index_sequence<sizeof...(BindArgs)>(), std::make_index_sequence<function_traits<Function>::arity - sizeof...(BindArgs)>());
#endif
		}

	private:
		const int bindCount;
		Function mCall;
		std::tuple<BindArgs...> bindArgs;
	};

	template <typename R, typename Cla, typename... Args, typename... BindArgs>
	class CPFunction<R(Cla::*)(Args...), BindArgs...> : public IBinderTemplate
	{
		using Function = R(Cla::*)(Args...);
	public:
		CPFunction(Function func, Cla* obj, BindArgs&&...bindArgs)
			: mCall(func), mObj(obj), bindArgs(std::forward<BindArgs&&>(bindArgs)...), bindCount(sizeof...(BindArgs))
		{
		}

		virtual Object Call(void* args, int count) override
		{
			check(function_traits<Function>::arity, sizeof...(BindArgs), count);
			using Ret = typename function_traits<Function>::Ret;
#ifdef CPP_HAS_17
			return CallBack<Ret, Function, Function, Cla>(args, mObj, mCall, bindArgs, std::make_index_sequence<sizeof...(BindArgs)>(), std::make_index_sequence<function_traits<Function>::arity - sizeof...(BindArgs)>());
#else
			Ret* temp = 0;
			return CallBack<Ret, Function, Function, Cla>(temp, args, mObj, mCall, bindArgs, std::make_index_sequence<sizeof...(BindArgs)>(), std::make_index_sequence<function_traits<Function>::arity - sizeof...(BindArgs)>());
#endif
		}

	private:
		const int bindCount;
		Function mCall;
		Cla* mObj;
		std::tuple<BindArgs...> bindArgs;
	};

	template <typename R, typename Cla, typename... Args, typename... BindArgs>
	class CPFunction<R(Cla::*)(Args...) const, BindArgs...> : public IBinderTemplate
	{
		using Function = R(Cla::*)(Args...)const;
	public:
		CPFunction(Function func, Cla* obj, BindArgs&&...bindArgs)
			: mCall(func), mObj(obj), bindArgs(std::forward<BindArgs&&>(bindArgs)...), bindCount(sizeof...(BindArgs))
		{
		}

		virtual Object Call(void* args, int count) override
		{
			check(function_traits<Function>::arity, sizeof...(BindArgs), count);
			using Ret = typename function_traits<Function>::Ret;
#ifdef CPP_HAS_17
			return CallBack<Ret, Function, Function, Cla>(args, mObj, mCall, bindArgs, std::make_index_sequence<sizeof...(BindArgs)>(), std::make_index_sequence<function_traits<Function>::arity - sizeof...(BindArgs)>());
#else
			Ret* temp = 0;
			return CallBack<Ret, Function, Function, Cla>(temp, args, mObj, mCall, bindArgs, std::make_index_sequence<sizeof...(BindArgs)>(), std::make_index_sequence<function_traits<Function>::arity - sizeof...(BindArgs)>());
#endif
		}

	private:
		const int bindCount;
		Function mCall;
		Cla* mObj;
		std::tuple<BindArgs...> bindArgs;
	};

	template <typename R, typename Cla, typename... Args, typename... BindArgs>
	class CPFunction<R(Cla::*)(Args...) volatile, BindArgs...> : public IBinderTemplate
	{
		using Function = R(Cla::*)(Args...) volatile;
	public:
		CPFunction(Function func, Cla* obj, BindArgs&&...bindArgs)
			: mCall(func), mObj(obj), bindArgs(std::forward<BindArgs&&>(bindArgs)...), bindCount(sizeof...(BindArgs))
		{
		}

		virtual Object Call(void* args, int count) override
		{
			check(function_traits<Function>::arity, sizeof...(BindArgs), count);
			using Ret = typename function_traits<Function>::Ret;
#ifdef CPP_HAS_17
			return CallBack<Ret, Function, Function, Cla>(args, mObj, mCall, bindArgs, std::make_index_sequence<sizeof...(BindArgs)>(), std::make_index_sequence<function_traits<Function>::arity - sizeof...(BindArgs)>());
#else
			Ret* temp = 0;
			return CallBack<Ret, Function, Function, Cla>(temp, args, mObj, mCall, bindArgs, std::make_index_sequence<sizeof...(BindArgs)>(), std::make_index_sequence<function_traits<Function>::arity - sizeof...(BindArgs)>());
#endif
		}

	private:
		const int bindCount;
		Function mCall;
		Cla* mObj;
		std::tuple<BindArgs...> bindArgs;
	};

	template <typename R, typename Cla, typename... Args, typename... BindArgs>
	class CPFunction<R(Cla::*)(Args...) const volatile, BindArgs...> : public IBinderTemplate
	{
		using Function = R(Cla::*)(Args...) const volatile;
	public:
		CPFunction(Function func, Cla* obj, BindArgs&&...bindArgs)
			: mCall(func), mObj(obj), bindArgs(std::forward<BindArgs&&>(bindArgs)...), bindCount(sizeof...(BindArgs))
		{
		}

		virtual Object Call(void* args, int count) override
		{
			check(function_traits<Function>::arity, sizeof...(BindArgs), count);
			using Ret = typename function_traits<Function>::Ret;
#ifdef CPP_HAS_17
			return CallBack<Ret, Function, Function, Cla>(args, mObj, mCall, bindArgs, std::make_index_sequence<sizeof...(BindArgs)>(), std::make_index_sequence<function_traits<Function>::arity - sizeof...(BindArgs)>());
#else
			Ret* temp = 0;
			return CallBack<Ret, Function, Function, Cla>(temp, args, mObj, mCall, bindArgs, std::make_index_sequence<sizeof...(BindArgs)>(), std::make_index_sequence<function_traits<Function>::arity - sizeof...(BindArgs)>());
#endif
		}

	private:
		const int bindCount;
		Function mCall;
		Cla* mObj;
		std::tuple<BindArgs...> bindArgs;
	};

private:
	std::unique_ptr<IBinderTemplate> pBinder;
};

}
#endif

使用案例

#include <iostream>
#include "./cp_core/cp_universal.h"

void function_normal_1(int a, double b)
{
	std::cout << "a =" << a << ", " << "b = " << b << std::endl;
}

int function_normal_2(int a, double b, char c)
{
	return a + b + c;
}

static int GetInt_normal(int a, int b)
{
	return a * a + b * b;
}

struct MyStruct
{
	static int GetInt(int a, int b)
	{
		return a * a + b * b;
	}

	int GetState(int a, int b)
	{
		return a + b;
	}

};

int Get(int a, float b)
{
	return a + b;
}

int main(int argc, char** argv)
{
	int a = 90;
	double b = 9090.99l;
	char c = 'C';

	// 无返回值
	CallBack::CPBind bind_nromal_1(function_normal_1, a);
	bind_nromal_1(1234.909);

	// 有返回值
	CallBack::CPBind bind_nromal_2(function_normal_2, a);
	CallBack::Object obj = bind_nromal_2(1234.909, c);

	// 静态函数, 注意: (int)b
	CallBack::CPBind bind_nromal_static_1(GetInt_normal, a, (int)b);
	CallBack::Object obj1 = bind_nromal_static_1();

	CallBack::CPBind bind__static_2(&MyStruct::GetInt, a, (int)b);
	CallBack::Object obj2 = bind__static_2();

	// 类成员函数
	MyStruct mys;
	CallBack::CPBind bind_class_1(&MyStruct::GetState, &mys, 10000, 90000);
	CallBack::Object obj3 = bind_class_1();


	// std::function
	std::function<int(int, float)> pfunc(&Get);
	CallBack::CPBind bind_function_1(pfunc, 1000);
	CallBack::Object obj4 = bind_function_1(90.97f);

	// 
	CallBack::CPBind bind_lambda([](int a, int b)->int { return a + b; }, 90);
	CallBack::Object obj5 = bind_lambda(10000);
	
	// 常函数我就不写了
	// 还有其他的自己测吧。不想写了。 引用啥的等等,我写的参数比较简单,自定义参数类型啥的等等
	return 0;
}

注意

这是第一版,里面可能有些东西可能使用更好的方式,慢慢来。欢迎指正。

  • 8
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值