《c++ templates》學習筆記(12)——第十七章 metaprogram

來源:互聯網
上載者:User
 

1       第十七章 metaprogram1.1    Metaprogram的第一個例子

書上舉了一個計算3的N次冪的例子,我將其擴充為計算M的N次冪。代碼如下:

template<int M, int N>

class Power{

public:

    enum{ result = M*Power<M, N-1>::result};

};

 

template<int M>

class Power<M, 0>{

public:

    enum { result = 1};

};

 

事實上,Template metaprograming後面所做的工作就是遞迴的模板執行個體化。

此處的Power就被稱為一個template metaprograming。它描述了一個可以在翻譯期求值的計算。

 

 

1.2    枚舉值和靜態常量

在老版的c++中(比如vc6),在類聲明的內部,枚舉值時聲明“真常值”的唯一方法。然而,現在的情況發生了變化,c++標準化過程中引入了在類內部進行靜態常量初始化的概念(在vs2003之後即可)。

所以,上面的枚舉值其實可以用靜態常量來代替。代碼如下:

template<int M, int N>

class Power{

public:

    //enum{ result = M*Power<M, N-1>::result};

    static int const result = M*Power<M, N-1>::result;

};

 

template<int M>

class Power<M, 0>{

public:

    //enum { result = 1};

    static int const result = 1;

};

得到的結果是一樣的。

然而,該版本存在一個缺點:靜態成員變數只能是左值。因此,如果你有一個如下聲明:

Void foo(int const&);

而且你把metaprogram的結果傳進去,即:

Foo(Power<3,4>::result>;

那麼編譯器必須傳遞Power<3,4>::result的地址。這會強制編譯器執行個體化靜態成員的定義,並且為該定義分配記憶體。

但是枚舉值卻不是左值(即沒有地址)。因此在你使用引用傳遞時,並不會使用任何靜態記憶體,就像是以文字常量的形式傳遞這個完成計算的值一樣。所以,我們一般鼓勵使用枚舉值

1.3    第二個例子:計算平方根

template<int N, int LO=0, int HI=N>

class Sqrt{

public:

    enum{ mid = (LO+HI+1)/2};

    enum{ result = (N<mid*mid) ? Sqrt<N,LO,mid-1>::result: Sqrt<N, mid, HI>::result};

};

 

template<int N, int M>

class Sqrt<N, M, M>{

public:

    enum{result = M};

};

 

int _tmain(int argc, _TCHAR* argv[])

{

    //17.3

    i = Sqrt<4>::result;

    return 0;

}

在上面的例子中,如果我們將其展開,那麼會得到:

    Sqrt<4>::result;

    //mid = (0+4+1)/2 = 2

    =(4<2*2)? Sqrt<4,0,1>::result : Sqrt<4, 2, 4>::result;

        //其中Sqrt<4,0,1>::result

        //mid = (0+1+1)/2=1

        =(4<1*1) ? Sqrt<4,0,0>::result : Sqrt<4, 1, 1>::result;

        =(4<1*1) ? 0:1;

        =1;

        //其中Sqrt<4, 2, 4>::result

        //mid=(2+4+1)/2=3

        =(4<3*3) ? Sqrt<4, 2, 2>::result : Sqrt<4, 3, 4>::result;

        =(4<9) ? 2 : Sqrt<4, 3, 4>::result;    

            //其中Sqrt<4, 3, 4>::result

            //mid = (3+4+1)/2=4

            =(4<4*4)? Sqrt<4, 3, 3>::result : Sqrt<4, 4, 4>::result;

            =(4<16)? 3 : 4;

            =3;

        =2

    =2

我們看到,上面得到了以下的這些執行個體化體:

Sqrt<4, 0, 0>::result

Sqrt<4, 1, 1>::result

Sqrt<4, 2, 2>::result

Sqrt<4, 3, 3>::result

Sqrt<4, 4, 4>::result

 

Sqrt<4, 0, 1>::result

Sqrt<4, 2, 4>::result

Sqrt<4, 3, 4>::result

 

由於代碼中試圖使用::運算子來訪問類的成員,所以類中的所有成員同時會被執行個體化。這就意味著:不僅執行個體化條件運算子正面分支的模板,還會執行個體化負面分支的模板。這將會導致龐大的執行個體化體。

對於任何編譯器來說,模板執行個體化通常都會是一個代價高昂的過程。

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.