C++11 模板元编程 - TypeList应用举例


使用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 class Unit__scatter_inherits()可以生成一个目标类,这个目标类继承自每个TypeList的元素应用Unit后的类型。下面是一个例子:

template struct Holder { T field; };

using Aggregator = __scatter_inherits(__type_list(int, short, char), Holder);

如上我们通过__scatter_inherits()创建了类型Aggregator,它多重继承自HolderHolderHolder(见下面图示)。

C++11 模板元编程 - TypeList应用举例_第1张图片

最终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模板元编程 - 目录

你可能感兴趣的:(C++11 模板元编程 - TypeList应用举例)