簡體   English   中英

基於枚舉模板參數的C ++成員函數的多個定義

[英]C++ Multiple definitons of member function, based on enum template argument

考慮以下代碼:

template<typename T, SomeEnum mode> struct TC{

    T data;

    //...

    void doStuff();
};

基於模板的枚舉值,“ doStuff”可以有多個定義嗎?

TC<int, SomeEnum::MODE_1> tc1;    tc.doStuff(); //do some stuff
TC<int, SomeEnum::MODE_2> tc2;    tc.doStuff(); //do some other stuff

(我並不是說保存“模式”並在其上創建一個分支,但實際上是多個定義。)

您可以執行標簽分配。 只需為枚舉的每個打包值提供一個重載:

template<typename T, SomeEnum mode> struct TC{

    T data;

    //...
    template<SomeEnum v>
    using tag_type = std::integral_constant<SomeEnum, v>;

    void reallyDoStuff(tag_type<SomeEnum::MODE_1>);
    void reallyDoStuff(tag_type<SomeEnum::MODE_2>);

    void doStuff() { reallyDoStuff(tag_type<mode>{}); }
};

因為除非使用,否則不會實例化類模板的成員函數,因此您只為每個TC實例實例化reallyDoStuff一個定義(正確的定義)。

如有疑問,請優先選擇功能模板重載而不是專業化。 通常是更好的選擇。

通常,這是模板專門用於的目的。 如果您不知道什么是模板專業化知識,則需要先閱讀C ++書籍,然后再閱讀其余的答案。

這里唯一的絆腳石是不能對單個類方法進行專門化,必須對整個類進行專門化。 但是有一些通用的解決方法,例如以下。

將成員函數定義為只是幫助程序模板類的函數調用包裝,如下所示:

template<typename T, SomeEnum mode> void TC::doStuff()
{
    doStuff_helper<T, mode>::doStuff(*this);
}

那就是你實際的doStuff()。 實際的代碼進入helper類。 如下定義助手類模板(當然,您將需要正確使用前向聲明和其他類似的用法):

template<typename T, SomeEnum mode> class doStuff_helper {
public:

   static void doStuff(TC<T, mode> &me)
   {
      // ...
   }
};

您原來的類方法所做的一切,現在都可以在這里完成,但有一些明顯的區別。 這不再是原始類的實際方法了。 因此,您可以在這里使用me作為參考,而不是原始的this 並且因為這不是實際的類方法,所以訪問私有或受保護的類成員時會遇到通常的問題。 但是這些都是次要細節,可以根據自身優點輕松解決。 關鍵是,您現在可以做的是將整個事情專門化:

template<typename T> class doStuff_helper<T, MODE_VALUE> {
public:

   static void doStuff(TC<T, MODE_VALUE> &me)
   {
      // ...
   }
};

現在, doStuff()可以完全不同了。 這是將不允許的分類方法專業化為普通的花園類分類專業的一般方法。

在這種通用方法上還有進一步的改進,這些改進是經常使用的。 這樣的改進之一就是讓doStuff()本身成為一個包裝器和對me的方法調用,而通用和專用版本則在原始模板類中調用不同的方法。

一旦您用紙和鉛筆弄清這里發生的情況,您將發現它最終的作用是將對原始doStuff()類方法的一次調用轉換為調用兩個不同的類方法(通常是private ),具體取決於原始模板類的參數。 這兩個不同的類方法實際上就是您最初想要的兩個不同版本的doStuff() ,僅根據模板參數使用適當的方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM