我正在研究迭代器,我在 github 上找到了一些源代碼。
我意識到這段代碼做了什么,但找不到怎么做。
template <class T>
struct _has_iterator_category
{
private:
struct _two { char _lx; char _lxx; };
template <class U> static _two _test(...);
template <class U> static char _test(typename U::iterator_category * = 0);
public:
static const bool value = sizeof(_test<T>(0)) == 1;
};
我認為這段代碼檢查是否T有 iterator_category,但我無法弄清楚它的作業原理和原因。
- 為什么這段代碼使用兩個模板?什么
class U模板? - 是
_test(...)函式還是建構式?什么是(...)手段?
2-1。如果_test是函式,這段代碼是在做函式多載嗎?那么如何多載不同的回傳型別呢?
2-2。如果_test是建構式,那么是charc 中的類嗎? * =運營商在做什么(typename U::iterator_category * = 0)?它是乘以指標iterator_category還是使iterator_category指標為0?- 什么
sizeof(_test<T>(0)) == 1;意思?如果sizeof(_test<T>(0))為 1,它是否回傳 true?
我搜索了很多檔案iterator_traits和其他內容,但未能解釋此代碼。
uj5u.com熱心網友回復:
首先,如果您了解 C ,則此代碼完全可以自行解釋。不需要有關外部組件的檔案。它不依賴于任何東西。您提出的問題表明在基本 C 語法理解方面存在一些差距。
1.模板定義_test是類模板的模板成員_has_iterator_category。它是在模板中定義的模板,所以即使你實體化了_has_iterator_category,你仍然需要_test稍后實體化,它有一個單獨的模板引數。
2.從技術上講,兩者都不是。因為類模板不是型別,而函式模板_test也不是函式。
建構式的名稱總是匹配最嵌套的封閉類范圍,即_has_iterator_category在這里。_has_iterator_category沒有宣告建構式。
它是一個函式模板。有兩個模板,用于不同的引數,具有不同的引數型別。如果兩個模板都可以通過用具體型別成功替換 U 來實體化,則函式被多載。
3.不是運算子* =,運算子中不能有空格。是*和=。這是引數串列的無名版本,可以用其他方式撰寫:
template <class U> static char _test(typename U::iterator_category *arg = 0);
= 0是函式引數的默認值arg。由于arg未在此背景關系中使用,因此可以跳過其名稱。
函式簽名的單個引數得到 type U::iterator_category *。typename是大多數但最近的 C 標準要求的關鍵字,用于依賴于模板引數的嵌套型別。這假定 U 必須具有嵌套型別
iterator_category。否則模板引數的替換將失敗。
template <class U> static _two _test(...);
這里的函式簽名是“可變的”。這意味著函式可以在替換模板引數后接受任意數量的引數。就像printf.
4. 如果結果的大小sizeof(_test<T>(0)) == 1等于1,則等于。true_test<T>(0)
整個結構是一種稱為 SFINAE 的規則形式 - 替換失敗不是錯誤。即使編譯器無法替換一個候選者,它仍然會嘗試其他候選者。當所有選項都用盡時,將診斷出該錯誤。
在這種情況下,運算式sizeof(_test<T>(0)),它試圖替換U為T。這就是為什么_test要做成嵌套模板的原因。該類是有效的,但現在我們檢查該函式。
如果 type-idT::iterator_category有效,則替換將成功,因為結果宣告將有效。_test(...)也可以成功,但是我們會超載選擇規則。
可變引數始終意味著型別轉換,因此沒有歧義并且_test(...)將被丟棄。
IfT::iterator_category不是有效型別,_two _test(...)是 的唯一實體_test()。
假設sizeof(char)等于 1,則使用if 運算式的回傳值將獲得與 相同的大小value來初始化常量。僅當存在時才是正確的。true_test<T>(0)charT::iterator_category
本質上,此構造檢查是否以某種笨拙和過時的方式class T包含嵌套型別T::iterator_category。但它與非常早期的 C 標準兼容,因為它不使用nullptr或<type_traits>標頭。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/486491.html
