我正在使用SFINAE構建一個基本的序列化庫。C++ SFINAE - std :: is_arithmetic和std :: is_same之間的分辨率優先級
比方說,我有一個類實現了一個通用的process
方法,該方法讀取任何類型(允許用戶擴展)並對其進行序列化。我正在使用std::enable_if
將此方法專用於不同的模板參數類型。下面是一個例子:
class OutputSerializer
{
public:
OutputSerializer(std::ostream& str) : stream(str) {}
private:
template<typename T>
typename std::enable_if<std::is_arithmetic<T>::value, void>::type
process(T&& arg) {
stream.write(&arg, sizeof(arg));
}
//More specializations here
std::ostream& stream;
};
我想優化該方法爲布爾值,通過使代替sizeof(bool)
字節輸出流存儲1字節,。與我以前的做法類似,我添加了一個新的模板專業化:
class OutputSerializer
{
public:
OutputSerializer(std::ostream& str) : stream(str) {}
private:
template<typename T>
typename std::enable_if<std::is_arithmetic<T>::value, void>::type
process(T&& arg) {
stream.write(&arg, sizeof(arg));
}
template<typename T>
typename std::enable_if<std::is_same<T, bool>::value, void>::type
process(T&& arg) {
stream.write(&arg, 1);
}
std::ostream& stream;
};
現在,出現了一個問題。 std::is_arithmetic<bool>
也應該返回true
。那麼在名稱解析過程中,哪兩項專業優先?
請記住,這只是一個理論問題。我知道的更多的方式來確保這個方法做什麼,我希望它如專業模板本身的布爾,像這樣:
template<>
void process<bool>(bool&& arg) {
stream.write(&arg, 1);
}
或通過增加在更一般的情況下,額外的檢查,這樣:
template<typename T>
typename std::enable_if<
std::is_arithmetic<T>::value
&& !std::is_same<T, bool>::value, void>::type
process(T&& arg) {
stream.write(&arg, sizeof(arg));
}
或者至少,我很確定這些工作。如果我錯了,請隨時打電話給我。謝謝!
您需要的'&&!的std :: is_same'否則你最終有兩個'無效處理(布爾)'。您不能擁有兩個具有相同名稱和簽名的功能。當然,你可以在函數內部使用if(std :: is_same ...),並且編譯器會正確地優化它,從而爲你節省很多頭痛的問題。 –
如果'sizeof(bool)!= 1',那麼你有一個'stream.write(&arg,1)'中的未定義行爲''對嗎? – freakish
爲什麼不只是做一個非模板重載,'void process(bool)'?非模板優先於模板,其他事情都是相等的。 –