在函數式語言中list基本都是遞歸式結構,類似:{elem, {elem, {elem, ...}}}
。
可以看到,基本結構是一個二元組{Head, Tail}
,Head是一個list節點,第二個元素Tail仍舊是一個類似的二元組,如此遞歸。
對于模板元編程無論list元素還是list本身都是類型,所以我們定義模板元編程的list結構如下:
// "tlp/list/TypeElem.h"
template<typename H, typename T>
struct TypeElem
{
using Head = H;
using Tail = T;
};
#define __type_elem(...) TypeElem<__VA_ARGS__>
有了TypeElem
,我們對其組合就得到了元素是類型的list。例如:
using List = TypeElem<char, TypeElem<int, TypeElem<long, TypeElem<short,NullType>>>>;
上例中,List是一個長度為4的類型列表,它的元素分別是char、int、long、short。最后的NullType是一個占位符,我們用它表示list的結束。
如果使用宏的版本,可以寫的稍微好看些:
using List = __type_elem(char, __type_elem(int, __type_elem(long, __type_elem(short, __null()))));
上述列表的結構雖然非常簡單,但是寫起來卻十分繁瑣。在定義list的時候要不停重復__type_elem
,非常不簡潔。下面我們提供一個構造元函數,用來簡化對list的定義。
// "tlp/list/algo/TypeList.h"
template<typename Head, typename ...Tails>
struct TypeList
{
using Result = TypeElem<Head, typename TypeList<Tails...>::Result>;
};
template<typename H>
struct TypeList<H>
{
using Result = TypeElem<H, NullType>;
};
#define __type_list(...) typename TypeList<__VA_ARGS__>::Result
如上TypeList是一個元函數,它通過變長模板參數來構造一個所有元素是類型的list結構。現在可以這樣定義list:__type_list(char, int, long, short)
,看起來非常的簡單直觀。
另外,對于全是數值的list,如 __type_list(__int(0), __int(1), __int(2))
的寫法也可以再簡單一些。如下我們提供了一個__value_list()
的語法糖。
// "tlp/list/algo/ValueList.h"
template<int Head, int ...Tails>
struct ValueList
{
using Result = TypeElem<IntType<Head>, typename ValueList<Tails...>::Result>;
};
template<int H>
struct ValueList<H>
{
using Result = TypeElem<IntType<H>, NullType>;
};
#define __value_list(...) typename ValueList<__VA_ARGS__>::Result
現在可以這樣定義:__value_list(0, 1, 2, 3)
,其本質和__type_list(__int(0), __int(1), __int(2))
是一樣的。
TEST("test value list")
{
ASSERT_EQ(__value_list(0, 1,2), __type_list(__int(0), __int(1), __int(2)));
};