使用C++0x新特性為模板參數指定約束條件

來源:互聯網
上載者:User

在編寫C++類模板時,有時希望模板參數滿足某種要求,即約束條件,比如要求某個模板型別參數T必須派生於基類TBase。

在C#泛型中可以通過where關鍵字來指定約束條件,而C++模板則缺乏類似的約束機制。

C++0x中引入了一些新的特性,C++標準庫也得到了改進和擴充,有兩篇不錯的參考文章:

Explicating the new C++ standard (C++0x), and its implementation in VC10Standard C++ Library changes in Visual C++ 2010

利用這些新特性,可以為模板參數指定一些約束。

比如,WTL中的模板,其中的一些模板參數必須從指定類繼承(直接或間接繼承),才能編譯通過,如CApplicationT類:

template<typename T, typename TMainWindow, bool bInitializeCom = false>
class CApplicationT :
    public CAppModule
{
public:
    //Call this method in the application's entry point[_tWinMain(...)]
    int WinMain(HINSTANCE hInstance,LPTSTR lpCmdLine,int nCmdShow)
    {
        //Ensure that TMainWindow is derived from CWindow
        static_assert(std::is_base_of<CWindow,TMainWindow>::value,
            "TMainWindow needs to be CWindow based.");
        UNREFERENCED_PARAMETER(lpCmdLine);
        T* pT = static_cast<T*>(this);
        //......
        int nRet = 0;
        {
            CMessageLoop msgLoop;
            AddMessageLoop(&msgLoop);
            TMainWindow wndMain;
            _g_hMainWindow = wndMain.Create(NULL,CWindow::rcDefault);
            if(_g_hMainWindow == NULL)
            {
                ATLTRACE(_T("Failed to create Main window!\n"));
                return 0;
            }
            wndMain.ShowWindow(nCmdShow);
            wndMain.UpdateWindow();
            wndMain.CenterWindow();
            //......

這個模板類有個型別參數TMainWindow,實現代碼中調用了這個類的一些成員函數,如Create(…),ShowWindow()等等。然而,這些成員函數實際上是CWindow類的成員函數。也就是說,TMainWindow類必須從CWindow類繼承(直接或間接繼承),才能在模板執行個體化時正確編譯通過。

否則,如果TMainWindow不是CWindow的衍生類別,在編譯如下代碼時:

CApplication<CTestWindow> g_MainApp;

編譯器會提示如下錯誤:

e:\coding\mywtllib\wtlapp.h(56): error C2039: 'Create' : is not a member of 'CTestWindow'
d:\cpp\wtl\wtlapp\win7shell\mainapp.cpp(6) : see declaration of 'CTestWindow'

e:\coding\mywtllib\wtlapp.h(62): error C2039: 'ShowWindow' : is not a member of 'CTestWindow'

       d:\cpp\wtl\wtlapp\win7shell\mainapp.cpp(6) : see declaration of 'CTestWindow'

這種編譯錯誤不夠直觀,當碰到某些不太常見的成員函數時,特別是使用別人編寫的模板代碼,又缺少文檔說明時,很難搞清楚TMainWindow應當滿足什麼條件才能編譯通過。

 

幸好,我們現在可以利用C++0x的一些新特性來顯式指定TMainWindow必須從CWindow類繼承(直接或間接繼承),方法為在CApplicationT模板實現代碼中添加一段靜態斷言代碼:

template<typename T, typename TMainWindow, bool bInitializeCom = false>
class CApplicationT :
    public CAppModule
{
public:
    //Call this method in the application's entry point[_tWinMain(...)]
    int WinMain(HINSTANCE hInstance,LPTSTR lpCmdLine,int nCmdShow)
    {
        //Ensure that TMainWindow is derived from CWindow
        static_assert(std::is_base_of<CWindow,TMainWindow>::value,
            "TMainWindow needs to be CWindow based.");
        UNREFERENCED_PARAMETER(lpCmdLine);
        T* pT = static_cast<T*>(this);
        //......

這樣,當TMainWindow不滿足條件時,編譯器就會提示如下錯誤:

e:\coding\mywtllib\wtlapp.h(25): error C2338: TMainWindow needs to be CWindow based.

這樣,錯誤原因就清晰多了。

使用std::is_base_of<>時,需要添加標頭檔”#include <type_traits>”

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.