eATM

封装回调函数扔掉的代码-_-

				
						using namespace traits;

	template<template<typename, typename...> typename T1, typename R1, typename ...Args1>
	class any_fun_operator
	{
		//using U1 = fun_traits<T1>;
		//using type0 = easy_traits<T1>;
	public:

		void call()
		{
			T1<R1> xxx;

			int x = 0;

		}


		/*
					template <typename T>
					typename std::enable_if<is_smart_pointer<T>::value, void>::type
						check_smart_pointer(const T& t)
					{
						std::cout << "is smart pointer" << std::endl;
					}

					template <typename T>
					typename std::enable_if<!is_smart_pointer<T>::value, void>::type
						check_smart_pointer(const T& t)
					{
						std::cout << "not smart pointer" << std::endl;
					}*/
					/*
								typename U1::ret_type operator()(typename U1::args_types)
								{
									int x = 0;
								}*/
	};

	/*
			template<typename T1, typename T2>
			class any_fun_operator
			{
				using type0 = easy_traits<T1>;
			public:
				typename type0::return_type operator()(typename type0::arguments)
				{
					int x = 0;
				}
			};*/

	template<typename ...Args>
	class any_fun
		//:public any_fun_operator<Args...>
	{
		static const size_t type_count = sizeof...(Args);	//类型个数
		static_assert(type_count > 0, "此类需要一个或多个模板参数,如:etd::function<std::function<void(void)>");

		template<std::size_t N>
		using typelist = typename std::tuple_element<N, std::tuple<Args...>>::type;

	private:
		constexpr static int ERR_NO_FIND = -1;
		constexpr static int ERR_TYPE_RE = -2;
	public:
		template<typename F>
		any_fun(F&& val)
		{
			constexpr auto const_Index = find_type<F>();

			//没有匹配的函数类型
			static_assert(!(const_Index == ERR_NO_FIND), "no match type");

			if constexpr (const_Index == ERR_TYPE_RE)
			{
				constexpr auto const_Index2 = find_type<F, 0, true>();

				//没有匹配的函数类型
				static_assert(!(const_Index2 == ERR_NO_FIND), "no match type");

				//该函数模板给出了重复类型
				static_assert(!(const_Index2 == ERR_TYPE_RE), "retype!");

				_data = (typelist<const_Index2>)std::move(val);
			} else {
				_data = (typelist<const_Index>)std::move(val);
			}
			using fun_traits = easy_traits<F>;
			easy_traits<F>::print();
			print_lists();

			int x = 0;
			/*
			auto sssss = sizeof(TTT);
			auto testval = std::is_same_v<int, short&>;
			auto test2 = std::is_convertible_v<int,char>;
			auto test3 = std::is_arithmetic_v<B>;
			double aaaaa = 1234567890;
							//int bbb = 0;
							//auto xxx = type_id<typelist<0>>().name();
							//using MY_T = myfun_traits<typelist<0>>;
							//auto a2 = get_fun_string<typename typelist<0>>();
							//std::cout << std::endl;
							//std::cout << get_return_type<typename typelist<0>>();
							//get_return_type<myfun_traits<FUN>::arg_type<0>>();
							//auto xxx = std::type_info(fun);
							int bbccb = 0;*/
		}

		/*
					template<typename RET_TYPE = void, typename... As>
					RET_TYPE operator()(As&& ... args)
					{

						//函数1参数类型
						if constexpr (!easy_traits<typelist<0>>:: template is_args_match<0, As...>())
						{

						}
					}*/

	private:

		//查找赋值时期的类型索引号
		//返回值:ERR_NO_FIND 没有找到匹配
		//返回值:ERR_TYPE_RE 找到多个匹配项
		//is_absolute 使用类型绝对匹配, 不使用自动转换.在如果找到多个匹配项下设置此值重新查找一遍.
		//Index:当前索引号
		//find_count:匹配次数,仅is_absolute==false时有效
		//find_index:找到的索引号
		template<typename T, size_t Index = 0, bool is_absolute = false, size_t find_count = 0, int find_index = -1>
		constexpr static int find_type()
		{
			if constexpr (Index >= type_count)			//结尾了
			{
				if constexpr (find_count == 1)
				{
					return find_index;					//OK 找到了
				} else if (find_count == 0)
				{
					return ERR_NO_FIND;				//没有找到
				} else {
					return ERR_TYPE_RE;				//找到多个匹配项
				}
			} else {

				if constexpr (!is_absolute)
				{
					if constexpr (std::is_convertible_v<T, typelist<Index>>)
					{
						return find_type<T, Index + 1, is_absolute, find_count + 1, Index>();
					} else {
						return find_type<T, Index + 1, is_absolute, find_count, find_index>();
					}
				} else {

					//类型绝对匹配
					if  constexpr (easy_traits<typelist<Index>>:: template cmp_types_absolute<T>())
					{
						return find_type<T, Index + 1, is_absolute, find_count + 1, Index>();
					} else {
						return find_type<T, Index + 1, is_absolute, find_count, find_index>();
					}
				}
			}
		}

		//打印所有函数类型列表
		template<size_t Index = 0>
		void print_lists()
		{
			if constexpr (Index >= type_count)
			{
				std::cout << "*************************************************************************\n";
				return;
			} else {
				if constexpr (Index == 0)
				{
					std::cout << "******************************函数类型列表*******************************\n";
				}

				using fun_traits = easy_traits<typelist<Index>>;
				fun_traits::print();

				print_lists<Index + 1>();
			}
		}

	private:
		std::any _data;
	};
}
				
			
				
					
//元编程类型
namespace easy {

	template <int val = 0>
	constexpr void static_print()
	{
		static_assert(val & false, "@debug output...");
	}

	//判断变量类型
	template <typename TYPE>
	struct var_type
	{
		//退化类型
		using BASE_TYPE = typename std::decay<TYPE>::type;

		constexpr static bool is_bool() {
			return is_type<bool>();
		};
		constexpr static bool is_int() {
			return is_type<int>();
		};
		constexpr static bool is_null_pointer() {
			return is_type<std::nullptr_t>();
		};

		template <typename TEST>
		constexpr static bool is_type() {
			//自动退化std::decay
			return std::is_same_v<BASE_TYPE, TEST>;
		};
	};

	//类型列表
	template<typename ...Args>
	struct type_list
	{

		//类型信息:types<i>
		template<std::size_t N>
		using types = typename std::tuple_element<N, std::tuple<Args...>>::type;

		//类型
		static const size_t count = sizeof...(Args);

		//比较列表-参数为 type_list
		template<typename T, size_t Index = 0>
		constexpr static bool cmp_list()
		{
			if constexpr (T::count != count)
			{
				return false;
			} else {
				if constexpr (Index == count)
				{
					return true;
				} else {
					if constexpr (std::is_same_v<types<Index>, typename T:: template types<Index>>)
					{
						return cmp_list<T, Index + 1>();
					} else {
						return false;
					}
				}
			}
		}
	};

	//函数
	template<typename T>
	struct fun_type;
	template<typename R, typename ...Args>
	struct fun_type<std::function<R(Args...)>>
	{
		typedef R result_type;						//返回值类型
		using args = type_list<Args...>;			//参数信息
	};

	/*
		//比较两组类型是否一致(两个args_traits类型)
		template<typename T1, typename T2, size_t Index = 0>
		constexpr static bool cmp_args_type()
		{
			if constexpr (T1::count != T2::count)
			{
				return false;
			} else {
				if constexpr (Index == T1::count)
				{
					return true;
				} else {
					if constexpr (std::is_same_v<typename T1:: template  types<Index>, typename T2:: template types<Index>>)
					{
						return cmp_args_type<T1, T2, Index + 1>();
					} else {
						return false;
					}
				}
			}
		}
	*/

	//判断参数类型
//template<typename T>
//struct param_type;

//通用函数类型
	template<typename ...Args>
	class eFun
	{
	public:
		template<std::size_t N>
		using types = typename std::tuple_element<N, std::tuple<Args...>>::type;

		//函数类型个数
		static const size_t count = sizeof...(Args);

		//构造函数
		template<typename T>
		eFun(T&& fun)
		{
			static_assert(count > 0, "该类需要添加函数类型.");

			//查找匹配的函数类型
			constexpr int Index = find_convertible<T, true>();

			if constexpr (Index == -1)
			{
				static_assert(Index >= 0, "不支持的函数类型.");
				return;
			}

			_data = std::move((types<Index>)fun);
		}

		//按照给定类型,查找类型能否转换
		//能的话返回其Index,否则返回-1
		//注意is_from变量
		template<typename T, bool is_from, int Index = 0>
		constexpr static int find_convertible()
		{
			if constexpr (Index >= count)
			{
				return -1;
			} else if constexpr (is_from ? std::is_convertible_v<T, types<Index>> : std::is_convertible_v<types<Index>, T>)
			{
				return Index;
			} else {
				return find_convertible<T, is_from, Index + 1>();
			}
		}

		/*
				//构造函数
				template<typename T>
				eFun(T&& t)
				{
					if constexpr (std::is_convertible_v<T, F1>)
					{
						fun = std::move((F1&&)t);
					} else if constexpr (std::is_convertible_v<T, F2>)
					{
						fun = std::move((F2&&)t);
					} else
					{
						//不支持回调函数类型
						static_assert(0, "easy error unknown callback type");
					}
				}

				//调用函数
				template<typename... Args>
				auto operator()(Args&& ... args)
				{
					//函数1参数类型
					typedef fun_type<F1>::args fun1_args;

					if  constexpr (fun1_args::is_match<Args...>())
					{
						int x = 0;
					} else {

						//参数类型错误.
						#ifdef WIN32
						static_assert(0, "param type error");
						#else
						static_assert(0, "参数类型错误");
						#endif
					}

					//constexpr auto i = args_type::nargs;

					//完全匹配函数

					return;
				}*/

	private:
		std::any _data;
		//int16_t _fun_type = -1;
	};

	using myFun = eFun<
		std::function<int(int)>
		, std::function<std::string(int)>
	>;


/*
	template<typename LAMBDA>
	struct function_traits
	{
		typedef decltype(((LAMBDA*)0)->operator()()) return_type;
		//using return_type = RET;
	};
	template<typename RET>
	struct function_traits<RET(*)()>
	{
		//typedef RET return_type;
		using return_type = RET;
	};
	template<typename RET, typename CLASS>
	struct function_traits<RET(CLASS::*)() const>
	{
		using return_type = RET;
	};

	template < typename F >
	void foo(F f) {

		using X = function_traits<F>::return_type;

		X abc;

		int x = 0;

		//return f();
	}*/
}
				
			
				
					#ifndef V8PP_UTILITY_HPP_INCLUDED
#define V8PP_UTILITY_HPP_INCLUDED

//修改自v8pp项目
//项目地址:https://github.com/pmed/v8pp

#include <functional>
#include <memory>
#include <string_view>
#include <tuple>
#include <type_traits>

namespace traits {

	template<typename T>
	struct tuple_tail;

	template<typename Head, typename... Tail>
	struct tuple_tail<std::tuple<Head, Tail...>>
	{
		using type = std::tuple<Tail...>;
	};

	struct none
	{
	};

	/////////////////////////////////////////////////////////////////////////////
	//
	// is_string<T>
	//
	template<typename T>
	struct is_string : std::false_type
	{
	};

	template<typename Char, typename Traits, typename Alloc>
	struct is_string<std::basic_string<Char, Traits, Alloc>> : std::true_type
	{
	};

	template<typename Char, typename Traits>
	struct is_string<std::basic_string_view<Char, Traits>> : std::true_type
	{
	};

	template<>
	struct is_string<char const*> : std::true_type
	{
	};

	template<>
	struct is_string<char16_t const*> : std::true_type
	{
	};

	template<>
	struct is_string<char32_t const*> : std::true_type
	{
	};

	template<>
	struct is_string<wchar_t const*> : std::true_type
	{
	};

	/////////////////////////////////////////////////////////////////////////////
	//
	// is_mapping<T>
	//
	template<typename T, typename U = void>
	struct is_mapping_impl : std::false_type
	{
	};

	template<typename T>
	struct is_mapping_impl<T, std::void_t<typename T::key_type, typename T::mapped_type,
		decltype(std::declval<T>().begin()), decltype(std::declval<T>().end())>> : std::true_type
	{
	};

	template<typename T>
	using is_mapping = is_mapping_impl<T>;

	/////////////////////////////////////////////////////////////////////////////
	//
	// is_sequence<T>
	//
	template<typename T, typename U = void>
	struct is_sequence_impl : std::false_type
	{
	};

	template<typename T>
	struct is_sequence_impl<T, std::void_t<typename T::value_type,
		decltype(std::declval<T>().begin()), decltype(std::declval<T>().end()),
		decltype(std::declval<T>().emplace_back(std::declval<typename T::value_type>()))>> : std::negation<is_string<T>>
	{
	};

	template<typename T>
	using is_sequence = is_sequence_impl<T>;

	/////////////////////////////////////////////////////////////////////////////
	//
	// has_reserve<T>
	//
	template<typename T, typename U = void>
	struct has_reserve_impl : std::false_type
	{
	};

	template<typename T>
	struct has_reserve_impl<T, std::void_t<decltype(std::declval<T>().reserve(0))>> : std::true_type
	{
	};

	template<typename T>
	using has_reserve = has_reserve_impl<T>;

	/////////////////////////////////////////////////////////////////////////////
	//
	// is_array<T>
	//
	template<typename T>
	struct is_array : std::false_type
	{
	};

	template<typename T, std::size_t N>
	struct is_array<std::array<T, N>> : std::true_type
	{
		static constexpr size_t length = N;
	};

	/////////////////////////////////////////////////////////////////////////////
	//
	// is_tuple<T>
	//
	template<typename T>
	struct is_tuple : std::false_type
	{
	};

	template<typename... Ts>
	struct is_tuple<std::tuple<Ts...>> : std::true_type
	{
	};

	/////////////////////////////////////////////////////////////////////////////
	//
	// is_shared_ptr<T>
	//
	template<typename T>
	struct is_shared_ptr : std::false_type
	{
	};

	template<typename T>
	struct is_shared_ptr<std::shared_ptr<T>> : std::true_type
	{
	};

	/////////////////////////////////////////////////////////////////////////////
	//
	// Function traits
	//
	template<typename F>
	struct function_traits;

	template<>
	struct function_traits<none>
	{
		using return_type = void;
		using arguments = std::tuple<>;
		template<typename D>
		using pointer_type = void;
	};

	template<typename R, typename... Args>
	struct function_traits<R(Args...)>
	{
		using return_type = R;
		using arguments = std::tuple<Args...>;
		template<typename D>
		using pointer_type = R(*)(Args...);
	};

	// function pointer
	template<typename R, typename... Args>
	struct function_traits<R(*)(Args...)>
		: function_traits<R(Args...)>
	{
	};

	// member function pointer
	template<typename C, typename R, typename... Args>
	struct function_traits<R(C::*)(Args...)>
		: function_traits<R(C&, Args...)>
	{
		using class_type = C;
		template<typename D>
		using pointer_type = R(D::*)(Args...);
	};

	// const member function pointer
	template<typename C, typename R, typename... Args>
	struct function_traits<R(C::*)(Args...) const>
		: function_traits<R(C const&, Args...)>
	{
		using class_type = C const;
		template<typename D>
		using pointer_type = R(D::*)(Args...) const;
	};

	// volatile member function pointer
	template<typename C, typename R, typename... Args>
	struct function_traits<R(C::*)(Args...) volatile>
		: function_traits<R(C volatile&, Args...)>
	{
		using class_type = C volatile;
		template<typename D>
		using pointer_type = R(D::*)(Args...) volatile;
	};

	// const volatile member function pointer
	template<typename C, typename R, typename... Args>
	struct function_traits<R(C::*)(Args...) const volatile>
		: function_traits<R(C const volatile&, Args...)>
	{
		using class_type = C const volatile;
		template<typename D>
		using pointer_type = R(D::*)(Args...) const volatile;
	};

	// member object pointer
	template<typename C, typename R>
	struct function_traits<R(C::*)>
		: function_traits<R(C&)>
	{
		using class_type = C;
		template<typename D>
		using pointer_type = R(D::*);
	};

	// const member object pointer
	template<typename C, typename R>
	struct function_traits<const R(C::*)>
		: function_traits<R(C const&)>
	{
		using class_type = C const;
		template<typename D>
		using pointer_type = const R(D::*);
	};

	// volatile member object pointer
	template<typename C, typename R>
	struct function_traits<volatile R(C::*)>
		: function_traits<R(C volatile&)>
	{
		using class_type = C volatile;
		template<typename D>
		using pointer_type = volatile R(D::*);
	};

	// const volatile member object pointer
	template<typename C, typename R>
	struct function_traits<const volatile R(C::*)>
		: function_traits<R(C const volatile&)>
	{
		using class_type = C const volatile;
		template<typename D>
		using pointer_type = const volatile R(D::*);
	};

	// function object, std::function, lambda
	template<typename F>
	struct function_traits
	{
		static_assert(!std::is_bind_expression<F>::value,
					  "std::bind result is not supported yet");

	private:
		using callable_traits = function_traits<decltype(&F::operator())>;

	public:
		using return_type = typename callable_traits::return_type;
		using arguments = typename tuple_tail<typename callable_traits::arguments>::type;
		template<typename D>
		using pointer_type = typename callable_traits::template pointer_type<D>;
	};

	template<typename F>
	struct function_traits<F&> : function_traits<F>
	{
	};

	template<typename F>
	struct function_traits<F&&> : function_traits<F>
	{
	};

	template<typename F>
	inline constexpr bool is_void_return = std::is_same_v<void, typename function_traits<F>::return_type>;

	template<typename F, bool is_class>
	struct is_callable_impl
		: std::is_function<typename std::remove_pointer<F>::type>
	{
	};

	template<typename F>
	struct is_callable_impl<F, true>
	{
	private:
		struct fallback { void operator()(); };
		struct derived : F, fallback {};

		template<typename U, U>
		struct check;

		template<typename>
		static std::true_type test(...);

		template<typename C>
		static std::false_type test(check<void (fallback::*)(), &C::operator()>*);

		using type = decltype(test<derived>(0));

	public:
		static constexpr bool value = type::value;
	};

	template<typename F>
	using is_callable = std::integral_constant<bool,
		is_callable_impl<F, std::is_class<F>::value>::value>;

	/// Type information for custom RTTI
	class type_info
	{
	public:
		constexpr std::string_view name() const { return name_; }
		constexpr bool operator==(type_info const& other) const { return name_ == other.name_; }
		constexpr bool operator!=(type_info const& other) const { return name_ != other.name_; }

	private:
		template<typename T> constexpr friend type_info type_id();

		constexpr explicit type_info(std::string_view name)
			: name_(name)
		{
		}

		std::string_view name_;
	};

	/// Get type information for type T
	/// The idea is borrowed from https://github.com/Manu343726/ctti
	template<typename T>
	constexpr type_info type_id()
	{
		#if defined(_MSC_VER) && !defined(__clang__)
		std::string_view name = __FUNCSIG__;
		const std::initializer_list<std::string_view> all_prefixes{ "type_id<", "struct ", "class " };
		const std::initializer_list<std::string_view> any_suffixes{ ">" };
		#elif defined(__clang__) || defined(__GNUC__)
		std::string_view name = __PRETTY_FUNCTION__;
		const std::initializer_list<std::string_view> all_prefixes{ "T = " };
		const std::initializer_list<std::string_view> any_suffixes{ ";", "]" };
		#else
		#error "Unknown compiler"
		#endif
		for (auto&& prefix : all_prefixes)
		{
			const auto p = name.find(prefix);
			if (p != name.npos)
			{
				name.remove_prefix(p + prefix.size());
			}
		}

		for (auto&& suffix : any_suffixes)
		{
			const auto p = name.rfind(suffix);
			if (p != name.npos)
			{
				name.remove_suffix(name.size() - p);
				break;
			}
		}

		return type_info(name);
	}

	template<typename F, size_t Offset = 0>
	struct easy_traits
	{
	private:
		static constexpr size_t offset = Offset;
		static constexpr bool is_mem_fun = std::is_member_function_pointer<F>::value;

	public:
		using arguments = typename function_traits<F>::arguments;
		
	private:
		template<size_t Index, bool>
		struct tuple_element
		{
			using type = typename std::tuple_element<Index, arguments>::type;
		};

		template<size_t Index>
		struct tuple_element<Index, false>
		{
			using type = void;
		};

	public:

		using return_type = typename function_traits<F>::return_type;

		static constexpr size_t arg_count = std::tuple_size<arguments>::value - is_mem_fun - offset;

		template<size_t Index>
		using arg_type = typename tuple_element < Index + is_mem_fun, Index<(arg_count + offset)>::type;

		//判断类型转换比较
		template<typename _from, typename _to>
		constexpr static bool is_conver()
		{
			if (std::is_same_v<_from, _to>)	//完全匹配.
			{
				return true;
			}
			return false;
		}

		//赋值时的类型绝对匹配
		template<typename T, int Index = -1>
		constexpr static bool cmp_types_absolute()
		{
			if constexpr (Index >= (int)arg_count)
			{
				return true;
			} else if constexpr (Index == -1)			//-1时检测参数个数与返回值类型
			{
				//检查参数个数
				if constexpr (arg_count != easy_traits<T>::arg_count)
				{
					return false;
				}

				//检查返回值类型
				if constexpr (!std::is_same_v<typename easy_traits<T>::return_type, return_type>)
				{
					return false;
				} else {
					return cmp_types_absolute<T, Index + 1>();
				}
			} else {
				if constexpr (!std::is_same_v<typename easy_traits<T>::template arg_type<Index>, arg_type<Index>>)
				{
					return false;
				} else {
					return cmp_types_absolute<T, Index + 1>();
				}
			}
		}

		//判断按照指定类型能否调用该函数
		template<typename RET_TYPE, typename... Args>
		constexpr static bool is_match_call()
		{
			return true;
		}

		//匹配参数列表
		template<size_t Index, typename... Args>
		constexpr static bool is_args_match()
		{
			constexpr size_t cur_size = sizeof... (Args);

			if constexpr (Index >= cur_size)
			{
				return true;
			} else {
				using cur_type = typename std::tuple_element<Index, std::tuple<Args...>>::type;

				if constexpr (!std::is_convertible_v<cur_type, arg_type<Index>>)
				{
					return false;
				} else {
					return is_args_match<Index + 1, Args...>();
				}
			}
		}

		//打印函数类型信息
		static void print(const char* sign = nullptr)
		{
			if (sign)
			{
				std::cout << sign << ":\t";
			}
			std::cout << get_return_type_string() << "(";
			print_args_string<arg_count, 0>();
			std::cout << ")" << std::endl;
		}

		//打印全部参数
		template<size_t count, size_t Index>
		static void print_args_string()
		{
			if constexpr (Index >= count)
			{
				return;
			} else {
				if constexpr (Index != 0)
				{
					std::cout << ",";
				}
				std::cout << get_args_type_string<Index>();
				print_args_string<count, Index + 1>();
			}
		}

		//得到返回类型字符串
		constexpr static  auto get_return_type_string()
		{
			return type_id<return_type>().name();
		}

		//得到指定位置参数类型字符串
		template<size_t Index>
		constexpr static auto get_args_type_string()
		{
			return type_id<arg_type<Index>>().name();
		}

		/*
				template<typename Arg, typename Traits,
					typename T = std::remove_reference_t<Arg>,
					typename U = std::remove_pointer_t<T>>
					using arg_converter = typename std::conditional_t<
					is_wrapped_class<std::remove_cv_t<U>>::value,
					std::conditional_t<std::is_pointer_v<T>,
					typename Traits::template convert_ptr<U>,
					typename Traits::template convert_ref<U>>,
					convert<std::remove_cv_t<T>>>;

				template<size_t Index, typename Traits>
				static decltype(auto) arg_from_v8(v8::FunctionCallbackInfo<v8::Value> const& args)
				{
					// might be reference
					auto result = (arg_converter<arg_type<Index>, Traits>::from_v8(args.GetIsolate(), args[Index - offset]));
					return result;
				}*/
	};
} // namespace traits

#endif // V8PP_UTILITY_HPP_INCLUDED
				
			
				
					
namespace detail {
	//出自:https://zhuanlan.zhihu.com/p/102240099

	template<typename R, typename ...As>
	struct __function_traits_base {
		using fun_type = std::function<R(As...)>;
		using ret_type = R;
		using args_types = std::tuple<As...>;
	};
	template<typename F>
	struct __function_traits;

	template<typename F>
	struct __function_traits<std::reference_wrapper<F>> : public __function_traits<F> {};

	template<typename R, typename ...As>
	struct __function_traits<R(*)(As...)> : public __function_traits_base<R, As...> {};

	template<typename R, typename C, typename ...As>
	struct __function_traits<R(C::*)(As...)> : public __function_traits_base<R, As...> {};

	template<typename R, typename C, typename ...As>
	struct __function_traits<R(C::*)(As...) const> : public __function_traits_base<R, As...> {};

	template<typename F>
	struct __function_traits : public __function_traits<decltype(&F::operator())> {};
}
template<typename F>
struct fun_traits : public detail::__function_traits<std::decay_t<F>> {};

/*
template <template<typename R1, typename ...Args> typename T1
	  , template<typename R, typename ...Args> typename T2>
auto test_1(std::function<R1(Args...)> && ff)
{
	R x;
	return 1;
}*/
				
			

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注