我想基於已經推導出的結構模板參數的類型特徵專門化模板結構體的成員函數。當模板參數被簽名時,我想要一個版本的函數,而另一個版本是未簽名的。不知道如何去做這件事。使用已經推導出的模板參數專門化模板成員函數
該結構很簡單。它代表了一個尺寸 - 無疑是寫了一千次。這裏有一個簡單的版本,我可以使用所有類型的,我想:
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>();
}
而且我猜還有其他方法。但我有點覺得我失去了一些明顯的東西。我總是喜歡花時間把這些東西簡化成最簡單,最清晰,最健壯的版本。
我意識到這不是一個非常複雜的「問題」。正如我所說,我已經可以讓代碼工作了。但是我正在尋找更一般的教訓 - 理解和認識所涉及的「模式」,因爲這是我經常遇到的那種情況。
因此,給出這些目標,是否有辦法更乾淨地或強有力地寫出這些?
我很感謝答案。我通常儘量不依賴編譯器來優化這些情況。我不確定我是否相信編譯器能夠識別並優化掉零和一個無符號類型的std :: max,特別是如果我想使用多個編譯器構建我的代碼時。我想我沒有使用你列出的方法,因爲在編譯時已知的情況下使用if語句似乎毫無意義。這就是type_traits的全部點,不是嗎? – Joe
@Joe依靠(平凡的)編譯器優化是一種不同的技術。在這裏你獲得更好的可讀代碼。 –
謝謝。我應該更信任我的編譯器。非常感激。 – Joe