使用TypeList可以一次对一组类型进行操纵,关于如何应用它是一个非常有想象力的事情。例如我们可以用TypeList轻易地实现一个trait工具,用于判断某一类型是否是C++内置类型:
// "tlp/traits/IsBuiltIn.h"
template
struct IsBuiltIn
{
private:
using BuiltInTypes = __type_list(char, wchar_t, char16_t, char32_t, bool, short, int, long, long long, float, double, long double);
public:
using Result = __is_included(BuiltInTypes, T);
};
#define __is_built_in(...) typename IsBuiltIn<__VA_ARGS__>::Result
TEST("estimate a type whether a built in type")
{
struct Object {};
ASSERT_TRUE(__is_built_in(char));
ASSERT_FALSE(__is_built_in(Object));
};
下面我们再介绍一种使用TypeList完成类型创建的设计技巧,这种设计技巧可以被用于C++自动代码生成,威力非常强大。
TLP中list的算法里有一个__scatter_inherits()
,它让用户传入一个TypeList,以及一个模板template
。__scatter_inherits()
可以生成一个目标类,这个目标类继承自每个TypeList的元素应用Unit后的类型。下面是一个例子:
template struct Holder { T field; };
using Aggregator = __scatter_inherits(__type_list(int, short, char), Holder);
如上我们通过__scatter_inherits()
创建了类型Aggregator
,它多重继承自Holder
、Holder
、Holder
(见下面图示)。
最终Aggregator
相当于有三个类型分别是int、short和char的成员变量。可以这样调用它的成员变量:
Aggregator object;
object.Holder::field = 5;
object.Holder::field = 'a';
__scatter_inherits()
的实现如下:
// "tlp/list/algo/ScatterInherits.h"
template class Unit> struct ScatterInherits;
template class Unit>
struct ScatterInherits
{
};
template class Unit>
struct ScatterInherits : Unit
{
};
template class Unit>
struct ScatterInherits, Unit>
: ScatterInherits
, ScatterInherits
{
};
#define __scatter_inherits(...) ScatterInherits<__VA_ARGS__>
__scatter_inherits()
的实现并不复杂,它采用多重继承的方式,递归地继承自Holder
。
有时我们想控制让这种继承关系能够保持单一继承。于是TLP同时提供了__linear_inherits()
,它的参数和__scatter_inherits()
相同,差别是__linear_inherits()
创建的类型的继承关系是一条单向继承链。
下面的代码示例中,我们创建了类型Aggregator
,它包含一组重载的成员方法void visit(const T& t)
。
template
struct Holder : Base
{
void visit(const T& t)
{
std::cout << t << std::endl;
};
};
using Aggregator = __linear_inherits(__type_list(int, short, char), Holder);
Aggregator object;
object.visit('a');
object.visit(-5);
上面代码示例中使用了__linear_inherits()
,所以Aggregator的继承关系图是线性的。关于__linear_inherits()
的具体实现请参考“tlp/list/algo/LinearInherits.h”。
这两个工具:__scatter_inherits()
和__linear_inherits()
都允许客户通过一个TypeList和一个Unit模板来做类型生成,差别仅在于目标类型的继承方式不同。它们的强大之处在于它们通过组合的手段来生成目标类型,而把组合元素以一个数据结构和算法的方式交给了客户。
Traits in TLP
返回 C++11模板元编程 - 目录