实现TypeList
template<typename T, typename U>
struct TypeList
{
using Head = T;
using Tail = U;
};
背后的机制
template参数可以是任何型别,包含该template的其他具现体。
作用
TypeList 内部没有任何数值:它们的实体是空的,不含任何状态,也未定义任何函数。执行期间t不带任何数值。它存在的理由只是为了携带型别信息。
使用
例子:
using CharList = TypeList<char, TypeList<signed char, char>>
优化
存在的问题1:
上述实现无法表达出拥有0个或1个类型的TypeList。
优化1: 增加结束标识
引入模板技术: NullType
struct NullType; // 无任何实现的类型,只是声明
就像C字符串一样,制定习惯:每个TypeList都必须以Nu11Type 结尾,将NullType当作其结束符。
实现持有一个类型的TypeList
template<typename T>
using OneTypeList = TypeList<T, NullType>;
存在的问题2:
利用原生的TypeList定义类型数组:
using SignedIntegrals = TypeList<signed char,
TypeList<short,
TypeList<int,
TypeList<long, NullType>>>>;
可以看出,用户使用起来太不友好,容易出错。
优化2: 可用性的线性化封装
引用的技术: C++11的using模板别名特性。
template<typename T>
using TypeList1 = TypeList<T, NullType>;
template<typename T1, typename T2>
using TypeList2 = TypeList<T1, TypeList1<T2>>;
template<typename T1, typename T2, typename T3>
using TypeList3 = TypeList<T1, TypeList2<T2, T3>>;
// ...
// 以下是伪代码
template<typename T1, ..., typename T50>
using TypeList50 = TypeList<T1, TypeList49<T2, ..., T50>>;
优点: 扩展性和可读性好
每个模板别名类使用前一个模板别名类,这让程序库使用者可以轻易扩充上限。
重新实现上述例子:
using SignedIntegrals = TypeList4<signed char, short, int, long>;
可以看出,更加的简洁直白,且用户不易写错。
问题3: 访问类型元素不便利
// 如果我们访问SignedIntegrals的最后一个类型
SignedIntegrals::Tail::Tail::Tail;
这样不够清晰易懂,写和理解都费事。
优化3: 模仿list类型,从长度入手。
1. 实现长度计算
背后的技术:模板类的偏特化+编译期整数计算
template<typename TypeList>
struct Length;
template<>
struct Length<NullType>
{
enum{ value = 0 };
};
template<typename T, typename U>
struct Length<TypeList<T, U>>
{
enum { value = 1 + Length<U>::value };
};
2. 索引式访问
背后的技术:模板偏特化+编译期递归
制定编译期算法:
template<typename TypeList, unsigned index>
struct TypeAt;
template<typename Head, typename Tail>
struct TypeAt<TypeList<Head, Tail>, 0>
{
using Result = Head;
};
template<typename Head, typename Tail, unsigned i>
struct TypeAt<TypeList<Head, Tail>, i>
{
using Result = typename TypeAt<Tail, i - 1>::Result;
};
再次实现访问的例子
// 获取SignedIntegrals的最后一个类型元素
TypeAt<SignedIntegrals, Length<SignedIntegrals> - 1>::Result;
问题4: 如何获取TypeList中某类型的位置?
优化4:
背后的技术:模板偏特化+编译期递归
制定编译期算法:
template<typename TypeList, typename T>
struct IndexOf;
template<typename T>
struct IndexOf<NullType, T>
{
enum { value = -1 };
};
template<typename Tail, typename T>
struct IndexOf<TypeList<T, Tail>, T>
{
enum { value = 0 };
};
template<typename Head, typename Tail, typename T>
struct IndexOf<TypeList<Head, Tail>, T>
{
private:
enum { temp = IndexOf<Tail, T>::value };
public:
enum { value = temp == -1 ? -1 : 1 + temp };
};