C++ 頭文件系列(system_error)


1.為什么system_error

"....report error conditions originating from the operating system or low-level application program interfaces."

報告源於操作系統低層程序接口錯誤。 更進一步說,< system_error >提供了用於報告該方面錯誤的異常機制,是<stdexcept>的擴展

2.怎么用system_error

物以類聚,功能也以“類”分。 剛看到這個頭文件的內容,我也有點懵逼,讓我們先理清類與類之間的關系:

class-relations-image

雖然這幾個類之間存在非常復雜的轉換構造關系(實際上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的能通過編譯。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM