C++11 模板元編程 - TypeList應用舉例


使用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模板元編程 - 目錄

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,915評論 18 139
  • 假如我們已經有了一組繼承體系: 如果我們要在其中增加一個新的動物mouse,只用新建一個Mouse類,讓它繼承自公...
    MagicBowen閱讀 5,251評論 0 2
  • 熟悉C++的程序員都知道,C++是一門多范式編程語言,支持面向過程、面向對象、泛型編程以及函數式編程范式。然而提到...
    MagicBowen閱讀 7,167評論 8 18
  • 1. Java基礎部分 基礎部分的順序:基本語法,類相關的語法,內部類的語法,繼承相關的語法,異常的語法,線程的語...
    子非魚_t_閱讀 31,765評論 18 399
  • 今天的便當是我期待已久的米飯三明治~配菜是黑椒蔬菜小炒和果蔬一夜漬~ 米飯三明治里面其實想放什么都可以,甚至今天的...
    森醬森醬閱讀 502評論 0 0