1.為什么system_error
"....report error conditions originating from the operating system or low-level application program interfaces."
報告源於操作系統或低層程序接口的錯誤。 更進一步說,< system_error >提供了用於報告該方面錯誤的異常機制,是對<stdexcept>的擴展。
2.怎么用system_error
物以類聚,功能也以“類”分。 剛看到這個頭文件的內容,我也有點懵逼,讓我們先理清類與類之間的關系:

雖然這幾個類之間存在非常復雜的轉換構造關系(實際上error_condition也可以通過error_category構造,但為了思路清晰,塗中沒有給出),但我們記住一點----system_error是runtime_error的子類,是異常類。 因此在使用時,我們只要抓住system_error類就行了,構造並拋出。
這里system_error主要有兩種構造方法:
- 借助error_code類構造
- 借助error_condition類(通常通過errc枚舉來構造)構造
這樣一來我們的使用思路就很清晰了,都在圖中,具體細節這里就不贅述了。
3.有趣的system_error
這里有個有趣的東西:
template <class T>
struct is_error_code_enum : public false_type {}
template <class T>
struct is_error_condition_enum : public false_type {}
從名字就能推測出,這兩個結構體用來控制其他類型到error_code和error_condition類型的自動轉換。 說到自動轉換,肯定是通過類的conversion constructor進行的。
那么問題就來了,想要能進行類型轉換,肯定得定義一個轉換構造器;如果不想,就不能定義。 但這里只通過顯示特化上面兩個類,就能實現上述行為,這是怎么做到的呢? 這利用了模板函數 對重載決議的影響,也就是SFINAE(Substitute Error Is Not An Error)。
3.1 SFINA
下面舉個例子:
template <class T>
struct MyType
{
};
template <>
struct MyType<double>
{
typedef double type;
};
template <class T, class TT = typename MyType<T>::type>
void func(T t) { std::cout << "T" << std::endl; }
int main()
{
int i;
func(i); // ERROR!
func(12.3); // OK!
}
可以看到func模板函數有兩個類型參數,以個為直接參數T,另一個為推導參數TT(為成員類型MyType< T >::type),這兩個類型參數都需要在實例化時進行替換。 但是實際上我們只為MyType< double >類型定義了成員類型type,所以當函數func進行重載決議時發現MyType< int >類型沒有成員類型type,無法對TT類型進行替換,因此簽名為void func< int >(int t)的函數將會從重載函數集中去掉,結果就是不存在這樣的重載函數, 上面的兩個函數調用只有參數為double的能通過編譯。
