抽換"運算"的前後 Part II

CRTP Curious Recursivly Template Pattern

CRTP 可以實現靜態多型。不使用任何的 vtable/vptr,就可以達到,依型別的不同,做不同的事。

這個 template 的用戶在使用的時候,是要繼承它並且傳遞自已的 type 進入到 templateT。此 code 的最有趣的地方是在 static_cast<T*>(this),它會試著靜態下轉到用戶 class T,而且保證成功。

於是 current_this 就會是一個用戶 T*this 型別。由 current_this 所操作的 method ,compiler 會去搜尋 T 有無此 method,沒有的話再向上去找 base class 有沒有,再沒有就會 compile error。由 T 的型別決定挷定的 method 在 compile time 時,就被 compiler 決定,就都不需要 runtime 的 vtable/vptr。也因為靜態就決定好了行為,也給了 Compiler 更多優化的機會。

template<typename T>
class Benchmark
{public:
    void run()
    {
       // setup
       auto starttime = ::GetTime();
       
       // static polymorphism
       auto current_this = static_cast<T*>(this);
       current_this->process_data();
       
       // teardown
       auto duration = ::GetTime() - starttime;
       std::cout << duration << std::endl;
    }
 
 private:
    void process_data()
    {
         // default behavior
    };
};

class ImageProcess : public Benchmark<ImageProcess>
{
    void process_data()
    {
        // run algorithm 
    }
};
client code
ImageProcess image_process;
image_process.run();

實際上的應用可以在 Windows ATL 看到大量這種用法。

ex: class CMainDlg : public CDialogImpl<CMainDlg>

template <typename T> CDialogImpl; 就是 ATL 寫好的 CRT ,用戶 class 就是 CMainDlg ,在用的時候,會把自已的 CMainDlg 傳入 CDialogImpl,就可以選擇說要不要覆寫掉某些 CDialogImpl 的 method。

comments powered by Disqus