C++ Meta Programming基本上都是用template來做,它是Generic Programming的一種。個人認為這個東西在實際的開發中不是特別有用,至少我還沒有實際用過。TML(Type Manipunation Library)是作者開發的一個C++ Meta Programming庫,它是純粹為研究目的而寫的。如果你看了代碼不頭暈,說明你心理抵抗力比較強!在TML中,所有的代碼都運行在編譯期,它只對類型做操作而不對數據做操作。在整體結構上和
Standard Template Library (STL)相似,所不同的是TML將
類型放入容器中進行操縱而STL
將數據放入容器中進行操縱。當然,我這個小玩意還沒有完全成型,就算成型了也不可能與STL相提並論。下面先從原理上來進入TML正題:
1、靈感來源(TML的基礎)看看下面的一個模板類:
template <
typename A,
typename B>
class someName
{
typedef CASE<1, A,
CASE<2, B
> > type_list;
typedef FIND<type_list, 2>::RET RETURN;
public:
typedef RETURN RET;
};
這個類有兩個模板參數,在內部公共域僅提供了一個類型定義。我們將它翻譯成如下格式:
META_PARAMETERS<META_PARAM A, META_PARAM B>
META_FUNCTION someName
{
META_VAR CASE<1, A,
CASE<2, B
> > type_list;
META_VAR FIND<type_list, 2>::RET RET;
META_RETURN:
META_VAR RET RETURN;
};
這樣,原來的模板參數變成了函數參數,原來的類名someName變成了函數名,原來的類定義變成了函數體,以前的類私有域變成了函數執行運算的部分而公共域成了函數的返回部分。這樣以來,我們可以做如下的定義(或者,現在應該叫運算才對):
META_VAR someName<clsA, clsB>::RETURN clsResult;
這個語句不會在運行期產生任何內存分配行為,而對於編譯期來將將生成了一個新的類型。OK,TML的基本東西就這麼多了。如下的一些宏構成了TML的基礎部分:
#define META_EQUAL_TO :public
#define META_IS :public
#define META_FUNCTION class
#define META_PARAMETERS template
#define META_RETURN public
#define META_VAR typedef
#define META_PARAM typename
#define META_CONST(name,value) enum { name = (value) };
2、語句、運算和循環TML的語句相對來說簡單得多,一個最基本條件判斷語句如下:
META_PARAMETERS<bool condition, META_PARAM Then, META_PARAM Else>
META_FUNCTION IF
{
META_PARAMETERS<int _condition>
META_FUNCTION Select { META_RETURN: META_VAR Then RET; };
META_FUNCTION Select<false> { META_RETURN: META_VAR Else RET; };
META_RETURN:
META_VAR Select<condition>::RET RET;
};
實現的時候是通過一個嵌套類Select的特化來完成判斷操作。另外,說一句題外題內話,TML的所有返回都叫RET而不叫RETURN是因為寫起來麻煩。
TML也有一些運算符,比如:
META_PARAMETERS<META_PARAM UnaryFunc1, META_PARAM UnaryFunc2>
META_FUNCTION OR META_IS UNARY_FUNCTION
{
META_RETURN:
META_PARAMETERS<typename Arg>
META_FUNCTION EXEC
{
META_RETURN:
META_CONST(RET, (EXEC_UNARY_FUNCTION<UnaryFunc1, Arg>::RET
||EXEC_UNARY_FUNCTION<UnaryFunc2, Arg>::RET));
};
};
我估計,你看到這段代碼後根本就不知道它原來就是邏輯運算符OR的實現。其它的一些運算符號以後介紹。接下來一個比較頭痛的事情是循環。在TML裡,所有的循環都是通過
類型迭代來完成的,什麼是類型迭代,哎,我都崗不清楚,只可意會。看下面的例子:
META_PARAMETERS<META_PARAM MapList, META_PARAM Tag, META_PARAM Value>
META_FUNCTION PUSH_FRONT
{
META_VAR MapList::NEXT nextMap;
META_VAR MapList::VALUE VALUE;
META_VAR MapList::TAG TAG;
META_VAR MapList::PRIOR_TAG PRIOR_TAG;
META_VAR nextMap::TAG nextTAG;
META_VAR IF<
IS_SAME_TYPE::EXEC<nextTAG, map_private::END_NODE>::RET,
map_private::END_NODE,
PUSH_FRONT<nextMap, Tag, Value>
>::RET nextPushFront;
META_VAR IF<
IS_SAME_TYPE::EXEC<nextTAG, map_private::END_NODE>::RET,
map_private::MAP_NODE< TAG, VALUE, PRIOR_TAG, map_private::MAP_NODE<Tag, Value, TAG> >,
map_private::MAP_NODE< TAG, VALUE, PRIOR_TAG, nextPushFront::RET >
>::RET RET1;
META_RETURN:
META_VAR IF<
SIZE<MapList>::Value == 0,
map_private::MAP_NODE<Tag, Value>,
RET1
>::RET RET;
}; //PUSH_FRONT
nextPushFront在這裡起到了關鍵的作用,它讓類型迭代而產生我們想要的循環效果,最終從迭代的出口處得到我們想要的結果(RET)。