[英]C++ Change member function definition based on template parameter value
是否可以基於模板參數的值在函數中有條件地編譯語句? 例如:
template<typename T, bool chk>
class subject
{
public:
// the ideal case
void doSomething(T new_val)
{
if(chk)
{
if(new_val != val)
//do_something only if new_val is different from val
}
else
{
//do_something even if new_val and val are equal
}
}
//or if that's not possible, if chk = 0 use this method
void doSomething(T new_val)
{
//do_something even if new_val and val are equal
}
// and if chk = 1 use this method
void doSomething(T new_val)
{
if(new_val != val)
//do_something only if new_val is different from val
}
T val;
};
捕獲是基於chk的值,我什至都不希望將if(new_val!=val)
語句編譯到函數中(因為使用的每個T類型都必須定義!=運算符)。
我猜這種方法的一個缺點是foo<int,0>
和foo<int,1>
是不同的類,因此不可能定義一個不在乎chk是0還是1的函數(比如watch(foo<int>)
)。
我正在查看的應用程序專門是觀察者,對於某些類型,我只希望觀察者在值實際更改時得到通知,對於其他類型,我希望觀察者始終得到通知(對於那些我不希望的類型必須定義!=運算符)。
如果沒有兩個單獨的類,這是否可能?
如果沒有兩個單獨的類,這是否可能?
是的。 如果不想專門化您的類,以避免代碼重復,則可以使用以下示例中的sfinae表達式:
#include <type_traits>
#include <iostream>
template<typename T, bool chk>
struct subject {
template<bool trigger = chk>
std::enable_if_t<trigger>
doSomething(T new_val) {
if(new_val != val) {
std::cout << "new_val != val" << std::endl;
} else {
std::cout << "new_val == val" << std::endl;
}
}
template<bool trigger = chk>
std::enable_if_t<not trigger>
doSomething(T new_val) {
std::cout << "who cares?" << std::endl;
}
T val;
};
int main() {
subject<int, true> s1{0};
s1.doSomething(0);
s1.doSomething(1);
subject<int, false> s2{0};
s2.doSomething(0);
s2.doSomething(1);
}
這個想法是在編譯時就為doSomething
定義了正確的定義,它取決於模板參數chk
的值。 另一個定義只是簡單地按預期丟棄,根本無法使用。
請注意,要使sfinae表達式起作用, trigger
模板參數必須是成員函數模板的實際參數。 這就是為什么您必須這樣定義它的原因:
template<bool trigger = chk>
sfinae_expression_based_on_enable_if
doSomething(T new_val) { /* ... */ }
看到它在coliru上運行。
您正在尋找的被稱為“模板專業化”。
您將必須專門化您的模板。 在定義了基本模板之后,如上所述,您將繼續並定義其專業化:
template<typename T>
class subject<T, true>
{
public:
// ...
然后,對於第二個模板參數為true
(或false
,如果需要專門設置的話),您可以從頭開始定義整個subject
類,並進行所需的任何更改。 您可以刪除,添加或完全更改它們。 專門的類可以具有不同的類成員,方法或相同的類方法,但是它們的工作方式完全不同。
重要的是要了解您正在定義整個類,而不僅僅是定義不同的位。 如果確實只需要對該類的一個較小方面進行專門化,那么這當然會導致一堆重復的代碼; 因此通常需要對其進行重構,將不同的位放入幫助器類或函數中,並僅對不同的位進行專門化處理。
即將到來的C ++ 17標准還提供了一些其他的模板專業化替代方法。 但是在這種情況下,傳統上,專業化是第一要學的東西。 因此,在繼續學習C ++ 17的新知識之前,您應該將C ++書籍放到討論模板專業化的章節中,並首先掌握其中的知識。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.