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

2016-09-16  本文已影响432人  MagicBowen

使用TypeList可以一次对一组类型进行操纵,关于如何应用它是一个非常有想象力的事情。例如我们可以用TypeList轻易地实现一个trait工具,用于判断某一类型是否是C++内置类型:

// "tlp/traits/IsBuiltIn.h"

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

template<typename T> struct Holder { T field; };

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

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

最终Aggregator相当于有三个类型分别是int、short和char的成员变量。可以这样调用它的成员变量:

Aggregator object;

object.Holder<int>::field = 5;
object.Holder<char>::field = 'a';

__scatter_inherits()的实现如下:

// "tlp/list/algo/ScatterInherits.h"

template<typename TL, template<typename> class Unit> struct ScatterInherits;

template<template<typename> class Unit>
struct ScatterInherits<NullType, Unit>
{
};

template<typename Atom, template<typename> class Unit>
struct ScatterInherits : Unit<Atom>
{
};

template<typename Head, typename Tail, template<typename> class Unit>
struct ScatterInherits<TypeElem<Head, Tail>, Unit>
: ScatterInherits<Head, Unit>
, ScatterInherits<Tail, Unit>
{
};

#define __scatter_inherits(...) ScatterInherits<__VA_ARGS__>

__scatter_inherits()的实现并不复杂,它采用多重继承的方式,递归地继承自Holder<T>

有时我们想控制让这种继承关系能够保持单一继承。于是TLP同时提供了__linear_inherits(),它的参数和__scatter_inherits()相同,差别是__linear_inherits()创建的类型的继承关系是一条单向继承链。

下面的代码示例中,我们创建了类型Aggregator,它包含一组重载的成员方法void visit(const T& t)

template<typename T, typename Base>
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模板元编程 - 目录

上一篇 下一篇

猜你喜欢

热点阅读