2016-02-05 39 views
0

我想基於已經推導出的結構模板參數的類型特徵專門化模板結構體的成員函數。當模板參數被簽名時,我想要一個版本的函數,而另一個版本是未簽名的。不知道如何去做這件事。使用已經推導出的模板參數專門化模板成員函數

該結構很簡單。它代表了一個尺寸 - 無疑是寫了一千次。這裏有一個簡單的版本,我可以使用所有類型的,我想:

template<class T> 
struct Size 
{ 
    T cx; 
    T cy; 

    // ... a bunch of functions you might expect. 

    // normalize function -- avoid negative sizes. make sure size is at LEAST 0, 0 

    void normalize() 
    { 
     cx = std::min(cx, 0); 
     cy = std::min(cy, 0); 
    } 
}; 

課程,處理功能是毫無意義的無符號的類型,但卻。我想讓它對這些類型無效。

有一秒鐘,我想我可能會嘗試使用enable_if以及返回類型。

typename std::enable_if<std::is_signed<T>::value, Size&>::type 
normalize() 
{ 
    cx = std::max(cx, 0); 
    cy = std::max(cy, 0); 
    return *this; 
} 
typename std::enable_if<std::is_unsigned<T>::value, Size&>::type 
normalize() 
{ 
    return *this; 
} 

但是,這不會起作用,因爲(據我所知),因爲,在成員函數上的點,模板「T」已經推斷出,不能使用SFINAE。如果我錯了,請糾正我。

所以我想我可以寫true_type和false_type重載這樣的:

void normalize(std::true_type) 
{ 
    // Ensure signed types are at least zero. 

    cx = std::max(cx, 0); 
    cy = std::max(cy, 0); 
} 
void normalize(std::false_type) 
{ 
    // do nothing for unsigned types 
} 
void normalize() 
{ 
    // Call overload based on type. 
    normalize(std::is_signed<T>::type()); 
} 

但那些似乎毫無意義構建std::integral_constant<bool>。這冒犯了我的效率感。如果這是一個更復雜的例子,它甚至可能會影響性能。

所以不是我可以寫類似的成員模板函數是這樣的:

template <typename T> 
void normalizeT() 
{ } 

template<> 
void normalizeT<std::true_type>() 
{ 
    cx = std::max(cx, 0); 
    cy = std::max(cy, 0); 
} 
void normalize() 
{ 
    normalizeT<std::is_signed<T>::type>(); 
} 

而且我猜還有其他方法。但我有點覺得我失去了一些明顯的東西。我總是喜歡花時間把這些東西簡化成最簡單,最清晰,最健壯的版本。

我意識到這不是一個非常複雜的「問題」。正如我所說,我已經可以讓代碼工作了。但是我正在尋找更一般的教訓 - 理解和認識所涉及的「模式」,因爲這是我經常遇到的那種情況。

因此,給出這些目標,是否有辦法更乾淨地或強有力地寫出這些?

回答

0

不要手動優化(使用模板)。只是讓上std::max編譯器優化(注:你應該使用std::max「避免負尺寸」)

作出澄清或如果normalize實際上是比較複雜的,你可以這樣做:

void normalize() 
{ 
    if(std::is_signed<T>::value) { 
     cx = std::max(cx, 0); 
     cy = std::max(cy, 0); 
     // ... 
    } 
} 
+0

我很感謝答案。我通常儘量不依賴編譯器來優化這些情況。我不確定我是否相信編譯器能夠識別並優化掉零和一個無符號類型的std :: max,特別是如果我想使用多個編譯器構建我的代碼時。我想我沒有使用你列出的方法,因爲在編譯時已知的情況下使用if語句似乎毫無意義。這就是type_traits的全部點,不是嗎? – Joe

+0

@Joe依靠(平凡的)編譯器優化是一種不同的技術。在這裏你獲得更好的可讀代碼。 –

+0

謝謝。我應該更信任我的編譯器。非常感激。 – Joe

0

除非你也許爲嵌入式硬實時系統編寫代碼,這是過早優化的重點。即使它看起來不是最優的,你也應該編寫簡單易懂的代碼。編譯器甚至可以非常聰明地爲您優化掉std::max的呼叫!如果程序性能可以接受,那麼不會丟失任何東西:您已經編寫了一次代碼,並且一切正常。如果性能成爲一個問題,那麼不要猜測你應該剖析的瓶頸,只有當它顯示標準化爲無符號類型是你的問題領域(我無法想象任何情況,這將是真實的),你會考慮專門化它作爲無操作。

+0

我的同意建議之一。我想我選擇了一個不好的例子來問一個更一般的問題。在這種情況下,處理過於簡單。我只是想知道人們是如何傾向於解決這個問題的 - 當你真的需要根據已經推導出來的特質進行優化時。 Dieter基於特質(我們假設將被優化掉)的一個簡單「if」的建議對我來說聽起來很好。我只是想知道我是否錯過了一個更好的選擇。感謝你的回答 – Joe