簡體   English   中英

SFINAE:了解 void_t 和 detect_if

[英]SFINAE: Understanding void_t and detect_if

我正在學習模板元編程,最近,我在CPPConference上看到了一個關於 void_t 的演講。 不久之后,我發現了檢測成語

但是,我仍然很難理解其中任何一個(尤其是檢測習慣用法,因為它基於 void_t)。 我閱讀了這篇博文和這篇stackoverflow 文章,這對我有所幫助,但我仍然有一些問題。

如果我的理解是正確的,如果 void_t 中的表達式無效,它將使用以下表達式進行 SFINAEd 輸出:

template< class, class = std::void_t<> >
struct has_type_member : std::false_type { };

因為 class 在這里是一個默認的模板參數,它可以表示任意數量的獨立於其類型的參數? 甚至有必要說 class 等於 std::void_t<> 嗎? 寫出來還不夠

template< class, class = void >
struct has_type_member : std::false_type { };

如果不是,為什么?

但是,如果表達式有效,則此表達式將被稱為計算結果為 void:

template< class T >
struct has_type_member<T, std::void_t<typename T::type>> : std::true_type { };

為什么一個有效的表達式會被評估為 void,這對我們有什么幫助? 另外,為什么表達式需要有效才能匹配 void_t?

好吧,我並沒有聲稱我自己完全理解所有內容,但我會盡我所知盡力回答:

因為 class 在這里是一個默認的模板參數,它可以表示任意數量的獨立於其類型的參數?

幾乎。 此模板將匹配具有一兩個模板參數的任何實例化,因此所有形式都為has_type_member<T>has_type_member<T, U> 這是因為

  • class匹配任何類型。 但這並不特別(您也可以編寫class T您只是不需要名稱,因為您沒有在聲明中引用它)每個模板最初都匹配所有類型,並且只能通過參數數量來區分。 通常情況下,我們要么通過一些 SFINAE 魔術(如enable_if )進行約束,要么稍后通過部分模板規范更好地適應。
  • class = void匹配所有類型,如上所述,也根本沒有類型,因為如果我們沒有參數,則void填充。

我們只會將此模板實例化為has_member_type<T> ,因此這將始終是第一個匹配項,但可能不是最佳匹配項。 但是作為第一個匹配項,它告訴我們:第二個模板參數必須是void ,因為所有進一步的匹配項必須是部分規范。 否則我們就會產生歧義。 想一想,如果表達式有效,第二個模板會給我們int會發生什么。 然后我們有兩個匹配has_type_member<T, void>has_type_member<T, int> ,那么我們應該選擇哪個? 這就是為什么在成功的情況下,類型必須是void然后也選擇這個重載,因為它更特殊。

為什么一個有效的表達式會被評估為 void,這對我們有什么幫助? 另外,為什么表達式需要有效才能匹配 void_t?

所以第一個問題的第二部分我已經回答了。 關於第一個:想想void_t的定義:

template<class...>
using void_t = void;

那么, ...匹配所有類型和數量的所有內容,不是嗎? 實際上它只匹配一個有效的類型,如果不匹配它怎么可能使用這種類型? (我知道它不使用該類型,但它必須能夠使用。並且它不能使用無效類型)。 因此,如果傳遞的模板參數有效,它會給我們void 所以在我們的用例中:

如果T具有成員類型T::type ,則T::type是有效類型並且void_t<...>匹配它。 所以我們在這一點上得到void_t<T::type> ,它的計算結果為void ,它適合主要但更特殊,所以我們取它並得到一個true_type

如果我們沒有類型成員怎么辦? 那么表達式T::type是無效的, void_t<...>不能對其進行 mazch,因此部分規范無效,所以我們不能選擇它,但這沒問題,因為替換失敗不是錯誤,所以我們就去繼續我們已經找到的主模板。

甚至有必要說 class 等於 std::void_t<> 嗎? 寫出來還不夠

template< class, class = void > struct has_type_member : std::false_type { };

如果不是,為什么?

是的,它會,它也在談話中完成。 void_t<>字面上是void 我認為void_t只是為了與第二個規范更一致。 需要void_t ,因為我們需要這個 template.l

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM