編譯器: MSVC v142
所屬文件: xutility
位置(行): 259
函數(shù)名稱:_Unwrappable
函數(shù)描述:
_Unwrappable
函數(shù)的作用是檢查T
是否同時(shí)具有_Unwrapped
和_Seek_to
函數(shù), 以及確保_Unwrapped
可以作為參數(shù)傳遞給_Seek_to
. 如果兩個(gè)條件都滿足, 那么它就是一個(gè)_Unwrappable
對(duì)象, 即: 是一個(gè)迭代器.
源碼:
// FUNCTION TEMPLATE _Get_unwrapped
template <class _Iter, class = void>
struct _Unwrappable : false_type {};
template <class _Iter>
struct _Unwrappable<_Iter, void_t<decltype(_STD declval<_Iter&>()._Seek_to(_STD declval<const _Iter&>()._Unwrapped()))>>
: _Allow_inheriting_unwrap<_Iter>::type {};
?
模板匹配
void_t<decltype(_STD declval<_Iter&>()._Seek_to(_STD declval<const _Iter&>()._Unwrapped()))
, 又長(zhǎng)又臭的過濾條件.
C++
對(duì)待模板的套路就是利用 SFINAE
的失敗不會(huì)退出編譯而是跳過當(dāng)前匹配的原則, 也就是說如果當(dāng)前函數(shù)匹配過程出現(xiàn)任何失敗, 就表示這個(gè)T
不是一個(gè)Iterator
對(duì)象.
void_t
不管你返回的是什么類型签夭,反正它永遠(yuǎn)都是void, 它就是一個(gè)垃圾箱, 用它只是因?yàn)樗峁┝私邮苋魏晤愋蛥?shù), 正好可以利用這個(gè)機(jī)制把尖角括號(hào)內(nèi)部的表達(dá)式消化掉, 出錯(cuò)就跳過當(dāng)前匹配,不出錯(cuò)就表示第二個(gè)模板參數(shù)是一個(gè)void
.
decltype
和declval
搭配起來就是我可以不用實(shí)例化這個(gè)對(duì)象就可以檢查這個(gè)對(duì)象的某個(gè)方法返回的是什么類型(備注: 不執(zhí)行函數(shù)
), 這里使用它們這個(gè)組合有兩個(gè)目的, 一是檢查這個(gè)T
是否有_Seek_to
方法和_Unwrapped
方法, 二是檢查_Seek_to
的參數(shù)要求的類型跟_Unwrapped
返回的類型是否對(duì)的上. 這兩步檢查任何一個(gè)步驟出錯(cuò),_Unwrappable
函數(shù)就認(rèn)為T
不是一個(gè)Iterator
.
TODO: 為什么這里要檢查兩個(gè)成員函數(shù), 直接檢查_Unwrapped函數(shù)不就完事了嗎?
?
繼承
_Unwrappable
繼承了 _Allow_inheriting_unwrap<_Iter>::type
, 繼承過程中又再做了一層篩選, 主要是證明Iterator
的類別一致, 即證明你就是你.
template <class _Iter, class = void>
struct _Allow_inheriting_unwrap : true_type {};
template <class _Iter>
struct _Allow_inheriting_unwrap<_Iter, enable_if_t<!is_same_v<_Iter, typename _Iter::_Prevent_inheriting_unwrap>>>
: false_type {};