C++11可变数量模板参数可变类型模板参数并使用lamada函数调用使用范例

为了完成这个功能,耗费一整天。

背景是需要到一张表中查询,条件不一样,但是都可以通过PreparedStatement_setXX设置,想体验一把C++11的高级模板特性,设计如下封装


inline void set_para(PreparedStatement_T prepStat, int idx, std::string& str) {
			PreparedStatement_setString(prepStat, idx, str.c_str());
		}
		
		inline void set_para(PreparedStatement_T prepStat, int idx, int integer) {
			PreparedStatement_setInt(prepStat, idx, integer);
		}
这两个函数就是实际设置的函数,关键是怎么在主函数中分发给一个参数给这两个函数中的一个去执行

于是设计如下主函数:

template<typename Bean, typename... Arguments>
		inline std::list<Bean> exec_sql(
				std::function<void (ResultSet_T, std::list<Bean>)> result_cb, 
				std::string &sql, 
				Arguments... params) {
			//int paras_size = sizeof...(Arguments);
			std::tuple<Arguments...> args = std::make_tuple(std::forward<Arguments>(params)...);	

			std::list<Bean> result;
			Connection_T conn = ConnectionPool_getConnection(connectionPool);
			TRY {
				PreparedStatement_T prepStat = Connection_prepareStatement(conn, sql.c_str());
				set_para(prepStat, args, gen_seq<sizeof...(Arguments)>{});
				result_cb(PreparedStatement_executeQuery(prepStat), result);
			} CATCH(SQLException) {
				throw std::runtime_error(Exception_frame.message);
			} FINALLY {
				Connection_close(conn);
			}
			END_TRY;
			return result;
		}		

用tuple这是关键点之一,创建一个分发函数是关键点之二,gen_seq是关键点之三
set_para(prepStat, args, gen_seq<sizeof...(Arguments)>{});


gen_seq是我在网上搜索“如何获取可变模板参数索引”得到的答案,代码如下:

template <std::size_t... Ts>
	struct index {};

	template <std::size_t N, std::size_t... Ts>
	struct gen_seq : gen_seq<N - 1, N - 1, Ts...> {};

	template <std::size_t... Ts>
	struct gen_seq<0, Ts...> : index<Ts...> {};

这个代码比较深奥,我相信不是一般人能原创出来的,大家都是模仿。它的含义就是可以为每个可变参数生成一个索引,从0开始

gen_seq<sizeof...(Arguments)>
的展开过程介绍如下:

gen_seq(5)->gen_seq(4,4)->gen_seq(3,3,4)->gen_seq(2,2,3,4)->gen_seq(1,1,2,3,4)->gen_seq(0,0,1,2,3,4)->index(0,1,2,3,4)

于是乎就有了

index<Is...>即
index<0,1,2,3,4,5>
老外真是牛啊

 

分发函数如下:

template <typename... Args, std::size_t... Is>
		inline void set_para(PreparedStatement_T prepStat, std::tuple<Args...>& tup, index<Is...>) {
			auto l = {((set_para(prepStat, (Is + 1), std::get<Is>(tup))), 0)... };
			(void)l;
		}

这个函数也比较深奥啊,他的第一层意思是创建一个匿名对象,大括号里的代码才会执行,第二层意思是有一个可变长度的表达式要展开,第三层意思每个表达式的含义是setpara,为什么有可变表达式要展开呢,因为有可变索引的帮忙啊。


外面调用就很精练了,不比java的可读性差

std::string sql = "select * from xxx where Id='?'...
return exec_sql<xxx>([=](ResultSet_T resultSet, std::list<xxx>){...}, sql, para0, para1.。。。); 
lamada表达式再简单不过了,省略


不区分类型,不区分数量,一下全搞定。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值