模板设计和推导

看到QT的源码,梳理下模板相关问题分解和设计思路。

  1. 模板与函数的对应关系
	template<typename T> //入参:一个多个,模板形参所允许的类型
	struct SomeFunc      // 函数名称:对应声明的类名
	{
		static const int value = some_value; //返回值:通过该函数调用获得的类型或数值结果;
		using type = SomeType; 
	};

对某些函数中的“函数”不只用于形参列表的推导,也可用于形参的保存,对整个功能实现起辅助作用。
而且通常模板(函数)的原型声明不能够解决问题,而必须借助模板特化来达到目的。如:

//1. 中间类型定义,仅做索引缓存用,无函数的计算输出能力
template <size_t... args> struct IndexList;

//2. 函数的原型声明
struct IndexJoin<class IL1, class IL2>;
//3. 借助模板特化及编译器的类型推导和变参的合并能力达到目的
template <size_t... idxs1, size_t... idxs2> 
struct IndexJoin<IndexList<idxs1...>, IndexList<idxs2...>>
{
	using type = IndexList<idxs1..., idxs2...>;
};
  1. 实际问题的拆解推导过程
    解决的问题:
    从参数列表中取前N个;
    拆解和推导过程:
    1 通过模板特化,可以从完整的模板形参列表中取第1个,并且能够实现变参模板的形参拼接;
    2 逐次从变参列表中取第一个进行拼接,则可获取到前N个形参的列表。
    3 定义拆分及拼接的辅助模板,定义主模板调用辅助模板;
    /*
       The following List classes are used to help to handle the list of arguments.
       It follow the same principles as the lisp lists.
       List_Left<L,N> take a list and a number as a parameter and returns (via the Value typedef,
       the list composed of the first N element of the list
     */
    // With variadic template, lists are represented using a variadic template argument instead of the lisp way
    //1. 定义形参列表,用于形参的缓存,辅助功能实现
    template <typename...> struct List {};
    //2. 借助模板特化获取List的第一个形参,本质上也可以单独定义一个模板,用于取Head
    template <typename Head, typename... Tail> struct List<Head, Tail...> { typedef Head Car; typedef List<Tail...> Cdr; };
    //3. Append的函数的声明,输入为两个List,输出为拼接后的List
    template <typename, typename> struct List_Append;
    //输入参数:L1, L2
    template <typename... L1, typename...L2> 
    struct List_Append<List<L1...>, List<L2...>> { 
    	//返回值:Value
    	typedef List<L1..., L2...> Value; 
    }; 
    //4. 取前N个,可以理解为对前面定义的拆分函数、拼接函数的调用;
    //   调用方式是放在模板的形参列表中;
    template <typename L, int N> struct List_Left {
    	//辅助函数调用
        typedef typename List_Append<List<typename L::Car>,typename List_Left<typename L::Cdr, N - 1>::Value>::Value Value;
    };
    // 边界定义
    template <typename L> struct List_Left<L, 0> { typedef List<> Value; };

所以,模板设计时要把核心要解决的问题想清楚,然后看模板化下编译能够提供什么的能力,然后结合这些能力对问题进行细化拆解,定义相关的辅助函数,然后定义主函数调用辅助函数,最终达到预期效果。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值