From 39a95f6939417ebc5d8e716ca1664a1da1fc722c Mon Sep 17 00:00:00 2001
From: znone <glyc@sina.com.cn>
Date: Thu, 09 Feb 2017 12:04:19 +0000
Subject: [PATCH] 根据回调函数参数推断绑定的数据类型。

---
 include/qtl_common.hpp |  307 ++++++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 281 insertions(+), 26 deletions(-)

diff --git a/include/qtl_common.hpp b/include/qtl_common.hpp
index caf6c3e..e630599 100644
--- a/include/qtl_common.hpp
+++ b/include/qtl_common.hpp
@@ -14,6 +14,7 @@
 #include <type_traits>
 #include <tuple>
 #include <memory>
+#include <functional>
 #include "apply_tuple.h"
 
 namespace qtl
@@ -88,7 +89,9 @@
 	explicit indicator(data_type&& src) 
 		: is_null(false), is_truncated(false), length(0), data(std::move(src)) { }
 
+	operator bool() const { return is_null; }
 	operator data_type&() { return data; }
+	operator const data_type&() const { return data; }
 };
 
 template<typename Command, typename T>
@@ -119,15 +122,153 @@
 {
 
 template<typename F, typename T>
-auto apply(F&& f, T&& v) -> decltype(f(v))
+struct apply_impl
 {
-	return f(v);
-}
+private:
+	typedef typename std::result_of<F(T)>::type raw_result_type;
+	template<typename Ret, bool>
+	struct impl {};
+	template<typename Ret>
+	struct impl<Ret, true>
+	{
+		typedef bool result_type;
+		result_type operator()(F&& f, T&& v)
+		{
+			f(std::forward<T>(v));
+			return true;
+		}
+	};
+	template<typename Ret>
+	struct impl<Ret, false>
+	{
+		typedef Ret result_type;
+		result_type operator()(F&& f, T&& v)
+		{
+			return f(std::forward<T>(v));
+		}
+	};
+
+public:
+	typedef typename impl<raw_result_type, std::is_void<raw_result_type>::value>::result_type result_type;
+	result_type operator()(F&& f, T&& v)
+	{
+		return impl<raw_result_type, std::is_void<raw_result_type>::value>()(std::forward<F>(f), std::forward<T>(v));
+	}
+};
 
 template<typename F, typename... Types>
-auto apply(F&& f, std::tuple<Types...>&& v) -> decltype(apply_tuple(f, v))
+struct apply_impl<F, std::tuple<Types...>>
 {
-	return apply_tuple(f, v);
+private:
+	typedef typename std::remove_reference<F>::type fun_type;
+	typedef std::tuple<Types...> arg_type;
+	typedef typename std::result_of<F(Types...)>::type raw_result_type;
+	template<typename Ret, bool>
+	struct impl {};
+	template<typename Ret>
+	struct impl<Ret, true>
+	{
+		typedef bool result_type;
+		result_type operator()(F&& f, arg_type&& v)
+		{
+			apply_tuple(std::forward<F>(f), std::forward<arg_type>(v));
+			return true;
+		}
+	};
+	template<typename Ret>
+	struct impl<Ret, false>
+	{
+		typedef Ret result_type;
+		result_type operator()(F&& f, arg_type&& v)
+		{
+			return apply_tuple(std::forward<F>(f), std::forward<arg_type>(v));
+		}
+	};
+
+public:
+	typedef typename impl<raw_result_type, std::is_void<raw_result_type>::value>::result_type result_type;
+	result_type operator()(F&& f, arg_type&& v)
+	{
+		return impl<raw_result_type, std::is_void<raw_result_type>::value>()(std::forward<F>(f), std::forward<arg_type>(v));
+	}
+};
+
+template<typename Type, typename R>
+struct apply_impl<R (Type::*)(), Type>
+{
+private:
+	typedef R (Type::*fun_type)();
+	typedef R raw_result_type;
+	template<typename Ret, bool>
+	struct impl {};
+	template<typename Ret>
+	struct impl<Ret, true>
+	{
+		typedef bool result_type;
+		result_type operator()(fun_type f, Type&& v)
+		{
+			(v.*f)();
+			return true;
+		}
+	};
+	template<typename Ret>
+	struct impl<Ret, false>
+	{
+		typedef Ret result_type;
+		result_type operator()(fun_type f, Type&& v)
+		{
+			return (v.*f)();
+		}
+	};
+
+public:
+	typedef typename impl<raw_result_type, std::is_void<raw_result_type>::value>::result_type result_type;
+	result_type operator()(R (Type::*f)(), Type&& v)
+	{
+		return impl<raw_result_type, std::is_void<raw_result_type>::value>()(f, std::forward<Type>(v));
+	}
+};
+
+template<typename Type, typename R>
+struct apply_impl<R (Type::*)() const, Type>
+{
+private:
+	typedef R (Type::*fun_type)() const;
+	typedef R raw_result_type;
+	template<typename Ret, bool>
+	struct impl {};
+	template<typename Ret>
+	struct impl<Ret, true>
+	{
+		typedef bool result_type;
+		result_type operator()(fun_type f, Type&& v)
+		{
+			(v.*f)();
+			return true;
+		}
+	};
+	template<typename Ret>
+	struct impl<Ret, false>
+	{
+		typedef Ret result_type;
+		result_type operator()(fun_type f, Type&& v)
+		{
+			return (v.*f)();
+		}
+	};
+
+public:
+	typedef typename impl<raw_result_type, std::is_void<raw_result_type>::value>::result_type result_type;
+	result_type operator()(fun_type f, Type&& v)
+	{
+		return impl<raw_result_type, std::is_void<raw_result_type>::value>()(f, std::forward<Type>(v));
+	}
+};
+
+template<typename F, typename T>
+typename apply_impl<F, T>::result_type apply(F&& f, T&& v)
+{
+	return apply_impl<F, T>()(std::forward<F>(f),  std::forward<T>(v));
 }
 
 template<typename Command, size_t N, typename... Types>
@@ -182,6 +323,72 @@
 	{
 	}
 };
+
+#define QTL_ARGS_TUPLE(Arg, Others) \
+	typename std::tuple<typename std::decay<Arg>::type, typename std::decay<Others>::type...>
+
+template<typename Ret, typename Arg>
+inline typename std::decay<Arg>::type make_values(Ret (*)(Arg))
+{
+	return typename std::decay<Arg>::type();
+};
+
+template<typename Ret, typename Arg, typename... Others>
+inline auto make_values(Ret (*)(Arg, Others...)) -> QTL_ARGS_TUPLE(Arg, Others)
+{
+	return QTL_ARGS_TUPLE(Arg, Others)();
+};
+
+template<typename Type, typename Ret>
+inline Type make_values(Ret (Type::*)())
+{
+	return Type();
+};
+template<typename Type, typename Ret>
+inline Type make_values(Ret (Type::*)() const)
+{
+	return Type();
+};
+
+template<typename Type, typename Ret, typename... Args>
+inline auto make_values(Ret (Type::*)(Args...)) -> QTL_ARGS_TUPLE(Type, Args)
+{
+	return QTL_ARGS_TUPLE(Type, Args)();
+};
+template<typename Type, typename Ret, typename... Args>
+inline auto make_values(Ret (Type::*)(Args...) const) -> QTL_ARGS_TUPLE(Type, Args)
+{
+	return QTL_ARGS_TUPLE(Type, Args)();
+};
+
+template<typename Type, typename Ret, typename Arg>
+inline typename std::decay<Arg>::type make_values_noclass(Ret (Type::*)(Arg))
+{
+	return typename std::decay<Arg>::type();
+};
+template<typename Type, typename Ret, typename Arg>
+inline typename std::decay<Arg>::type make_values_noclass(Ret (Type::*)(Arg) const)
+{
+	return typename std::decay<Arg>::type();
+};
+
+template<typename Type, typename Ret, typename Arg, typename... Others>
+inline auto make_values_noclass(Ret (Type::*)(Arg, Others...)) -> QTL_ARGS_TUPLE(Arg, Others)
+{
+	return QTL_ARGS_TUPLE(Arg, Others)();
+};
+template<typename Type, typename Ret, typename Arg, typename... Others>
+inline auto make_values_noclass(Ret (Type::*)(Arg, Others...) const) -> QTL_ARGS_TUPLE(Arg, Others)
+{
+	return QTL_ARGS_TUPLE(Arg, Others)();
+};
+
+template<typename Functor, typename=typename std::enable_if<std::is_member_function_pointer<decltype(&Functor::operator())>::value>::type>
+inline auto make_values(const Functor&) 
+-> decltype(make_values_noclass(&Functor::operator()))
+{
+	return make_values_noclass(&Functor::operator());
+}
 
 }
 
@@ -452,88 +659,137 @@
 	}
 
 	template<typename Params, typename Values, typename ValueProc>
-	void query(const char* query_text, size_t text_length, const Params& params, Values&& values, ValueProc proc)
+	void query_explicit(const char* query_text, size_t text_length, const Params& params, Values&& values, ValueProc&& proc)
 	{
 		T* pThis=static_cast<T*>(this);
 		Command command=pThis->open_command(query_text, text_length);
 		command.execute(params);
 		while(command.fetch(std::forward<Values>(values)))
 		{
-			if(!detail::apply(proc, std::forward<Values>(values))) break;
+			if(!detail::apply(std::forward<ValueProc>(proc), std::forward<Values>(values))) break;
 		}
 		command.close();
 	}
 
 	template<typename Params, typename Values, typename ValueProc>
-	void query(const char* query_text, const Params& params, Values&& values, ValueProc proc)
+	void query_explicit(const char* query_text, const Params& params, Values&& values, ValueProc&& proc)
 	{
-		query(query_text, strlen(query_text), params, std::forward<Values>(values), proc);
+		query_explicit(query_text, strlen(query_text), params, std::forward<Values>(values), std::forward<ValueProc>(proc));
 	}
 	template<typename Params, typename Values, typename ValueProc>
-	void query(const std::string& query_text, const Params& params, Values&& values, ValueProc proc)
+	void query_explicit(const std::string& query_text, const Params& params, Values&& values, ValueProc&& proc)
 	{
-		query(query_text.data(), query_text.size(), params, std::forward<Values>(values), proc);
+		query_explicit(query_text.data(), query_text.size(), params, std::forward<Values>(values), std::forward<ValueProc>(proc));
 	}
 	template<typename Values, typename ValueProc>
-	void query(const char* query_text, size_t text_length, Values&& values, ValueProc proc)
+	void query_explicit(const char* query_text, size_t text_length, Values&& values, ValueProc&& proc)
 	{
-		query(query_text, text_length, std::make_tuple(), std::forward<Values>(values), proc);
+		query_explicit(query_text, text_length, std::make_tuple(), std::forward<Values>(values), std::forward<ValueProc>(proc));
 	}
 	template<typename Values, typename ValueProc>
-	void query(const char* query_text, Values&& values, ValueProc proc)
+	void query_explicit(const char* query_text, Values&& values, ValueProc&& proc)
 	{
-		query(query_text, strlen(query_text), std::make_tuple(), std::forward<Values>(values), proc);
+		query_explicit(query_text, strlen(query_text), std::make_tuple(), std::forward<Values>(values), std::forward<ValueProc>(proc));
 	}
 	template<typename Values, typename ValueProc>
-	void query(const std::string& query_text, Values&& values, ValueProc proc)
+	void query_explicit(const std::string& query_text, Values&& values, ValueProc&& proc)
 	{
-		query(query_text, std::make_tuple(), std::forward<Values>(values), proc);
+		query_explicit(query_text, std::make_tuple(), std::forward<Values>(values), std::forward<ValueProc>(proc));
+	}
+
+	template<typename Params, typename ValueProc>
+	void query(const char* query_text, size_t text_length, const Params& params, ValueProc&& proc)
+	{
+		query_explicit(query_text, text_length, params, detail::make_values(proc),  std::forward<ValueProc>(proc));
+	}
+	template<typename Params, typename ValueProc>
+	void query(const char* query_text, const Params& params, ValueProc&& proc)
+	{
+		query_explicit(query_text, params, detail::make_values(proc),  std::forward<ValueProc>(proc));
+	}
+	template<typename Params, typename ValueProc>
+	void query(const std::string& query_text, const Params& params, ValueProc&& proc)
+	{
+		query_explicit(query_text, params, detail::make_values(proc),  std::forward<ValueProc>(proc));
+	}
+	template<typename ValueProc>
+	void query(const char* query_text, size_t text_length, ValueProc&& proc)
+	{
+		query_explicit(query_text, text_length, detail::make_values(proc),  std::forward<ValueProc>(proc));
+	}
+	template<typename ValueProc>
+	void query(const char* query_text, ValueProc&& proc)
+	{
+		query_explicit(query_text, detail::make_values(proc),  std::forward<ValueProc>(proc));
+	}
+	template<typename ValueProc>
+	void query(const std::string& query_text, ValueProc&& proc)
+	{
+		query_explicit(query_text, detail::make_values(proc), std::forward<ValueProc>(proc));
 	}
 
 	template<typename Params, typename Values>
 	void query_first(const char* query_text, size_t text_length, const Params& params, Values&& values)
 	{
-		query(query_text, text_length, params, std::forward<Values>(values), first_record());
+		query_explicit(query_text, text_length, params, std::forward<Values>(values), first_record());
 	}
 
 	template<typename Params, typename Values>
 	void query_first(const char* query_text, const Params& params, Values&& values)
 	{
-		query(query_text, strlen(query_text), params, std::forward<Values>(values), first_record());
+		query_explicit(query_text, strlen(query_text), params, std::forward<Values>(values), first_record());
 	}
 
 	template<typename Params, typename Values>
 	void query_first(const std::string& query_text, const Params& params, Values&& values)
 	{
-		query(query_text, params, values, first_record());
+		query_explicit(query_text, params, values, first_record());
 	}
 
 	template<typename Values>
 	void query_first(const char* query_text, size_t text_length, Values&& values)
 	{
-		query(query_text, text_length, std::make_tuple(), std::forward<Values>(values), first_record());
+		query_explicit(query_text, text_length, std::make_tuple(), std::forward<Values>(values), first_record());
 	}
 
 	template<typename Values>
 	void query_first(const char* query_text, Values&& values)
 	{
-		query(query_text, strlen(query_text), std::make_tuple(), std::forward<Values>(values), first_record());
+		query_explicit(query_text, strlen(query_text), std::make_tuple(), std::forward<Values>(values), first_record());
 	}
 
 	template<typename Values>
 	void query_first(const std::string& query_text, Values&& values)
 	{
-		query(query_text, std::make_tuple(), std::forward<Values>(values), first_record());
+		query_explicit(query_text, std::make_tuple(), std::forward<Values>(values), first_record());
+	}
+
+	template<typename... Values>
+	void query_first_direct(const char* query_text, size_t text_length, Values&... values)
+	{
+		query_first(query_text, text_length, std::tie(values...));
+	}
+
+	template<typename... Values>
+	void query_first_direct(const char* query_text, Values&... values)
+	{
+		query_first(query_text, std::tie(values...));
+	}
+
+	template<typename... Values>
+	void query_first_direct(const std::string& query_text, Values&... values)
+	{
+		query_first(query_text, std::tie(values...));
 	}
 
 protected:
 	struct nothing 
 	{
-		template<typename... Values> bool operator()(Values&...) const {  return true; }
+		template<typename... Values> bool operator()(Values&&...) const {  return true; }
 	};
 	struct first_record 
 	{
-		template<typename... Values> bool operator()(Values&...) const {  return false; }
+		template<typename... Values> bool operator()(Values&&...) const {  return false; }
 	};
 };
 
@@ -593,6 +849,5 @@
 }
 
 }
-
 
 #endif //_MYDTL_DATABASE_H_

--
Gitblit v1.9.3