2017-05-13 74 views
0

我正在使用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)); 
} 

或者至少,我很確定這些工作。如果我錯了,請隨時打電話給我。謝謝!

+0

您需要的'&&!的std :: is_same'否則你最終有兩個'無效處理(布爾)'。您不能擁有兩個具有相同名稱和簽名的功能。當然,你可以在函數內部使用if(std :: is_same ...),並且編譯器會正確地優化它,從而爲你節省很多頭痛的問題。 –

+0

如果'sizeof(bool)!= 1',那麼你有一個'stream.write(&arg,1)'中的未定義行爲''對嗎? – freakish

+0

爲什麼不只是做一個非模板重載,'void process(bool)'?非模板優先於模板,其他事情都是相等的。 –

回答

2

沒有任何優先權。這兩個模板都會導致功能void process(bool),並且呼叫將不明確。

Example

增加對bool明確的專業化不會工作,因爲沒有明確的基本模板專攻。您需要向std::is_arithmetic版本的模板添加更多條件,或者更好的是爲bool提供非模板超載。函數優先於函數模板,所以非模板版本將通過重載解析來選擇。

Example

相關問題