国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 學(xué)院 > 開(kāi)發(fā)設(shè)計(jì) > 正文

C++ std::enable_if解析

2019-11-14 09:16:58
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

引言

今日在閱讀LLVM相關(guān)源碼時(shí)(如下所示),遇到了enable_if<>這個(gè)概念,以前從沒(méi)有遇到過(guò),這里做個(gè)小記。

/*----------llvm/include/llvm/ADT/Hashing.h------------*//// /brief Compute a hash_code for any integer value.////// Note that this function is intended to compute the same hash_code for/// a particular value without regard to the PRe-promotion type. This is in/// contrast to hash_combine which may produce different hash_codes for/// differing argument types even if they would implicit promote to a common/// type without changing the value.template <typename T>typename std::enable_if<is_integral_or_enum<T>::value, hash_code>::typehash_value(T value);123456789101112123456789101112

enable_if 的主要作用就是當(dāng)某個(gè) condition 成立時(shí),enable_if可以提供某種類型。enable_if在標(biāo)準(zhǔn)庫(kù)中通過(guò)結(jié)構(gòu)體模板實(shí)現(xiàn)的,聲明如下:

template<bool Cond, class T = void> struct enable_if;11

英文解釋如下:

Enable type if the condition is met. The type T is enabled as member type enable_if::type if Cond is true. Otherwise, enable_if::type is not defined.

但是當(dāng) condition 不滿足的時(shí)候,enable_if<>::type 就是未定義的,當(dāng)用到模板相關(guān)的場(chǎng)景時(shí),只會(huì) instantiate fail,并不會(huì)編譯錯(cuò)誤,這時(shí)很重要的一點(diǎn)。為了理解 std::enable_if<> 的實(shí)現(xiàn),我們先來(lái)了解一下 SFINAE。


SFINAE

SFINAE 是C++ 的一種語(yǔ)言屬性,具體內(nèi)容就是”從一組重載函數(shù)中刪除模板實(shí)例化無(wú)效的函數(shù)”。

Prune functions that do not yield valid template instantiations from a set of overload functions.

SFINAE 的的全稱是 Substitution Failure Is Not An Error。

SFINAE 應(yīng)用最為廣泛的場(chǎng)景是C++中的 std::enable_if,這里有完整的英文描述:

In the process of template argument deduction, a C++ compiler attempts to instantiate signatures of a number of candidate overloaded functions to make sure that exactly one overloaded function is available as a perfect match for a given function call.

從上面的描述中我們可以看到,在對(duì)一個(gè)函數(shù)調(diào)用進(jìn)行模板推導(dǎo)時(shí),編譯器會(huì)嘗試推導(dǎo)所有的候選函數(shù)(重載函數(shù),模板,但是普通函數(shù)的優(yōu)先級(jí)要高),以確保得到一個(gè)最完美的匹配。

If an invalid argument or return type is formed during the instantiation of a function template, the instantiation is removed from the overload resolution set instead of causing a compilation error. As long as there is one and only one function to which the call can be dispatched, the compiler issues no errors.

也就是說(shuō)在推導(dǎo)的過(guò)程中,如果出現(xiàn)了無(wú)效的模板參數(shù),則會(huì)將該候選函數(shù)從重載決議集合中刪除,只要最終得到了一個(gè) perfect match ,編譯就不會(huì)報(bào)錯(cuò)。

如下代碼所示:

long multiply(int i, int j) { return i * j; }template <class T>typename T::multiplication_result multiply(T t1, T t2){    return t1 * t2;}int main(void){    multiply(4, 5);}123456789101112123456789101112

main 函數(shù)調(diào)用 multiply 會(huì)使編譯器會(huì)盡可能去匹配所有候選函數(shù),雖然第一個(gè) multiply 函數(shù)明顯是較優(yōu)的匹配,但是為了得到一個(gè)最精確的匹配,編譯器依然會(huì)嘗試去匹配剩下的候選函數(shù),此時(shí)就會(huì)去推導(dǎo) 第二個(gè)multiply函數(shù),中間在參數(shù)推導(dǎo)的過(guò)程中出現(xiàn)了一個(gè)無(wú)效的類型 int::multiplication_result ,但是因?yàn)?nbsp;SFINAE 原則并不會(huì)報(bào)錯(cuò)。


std::enable_if<> 的實(shí)現(xiàn)

前面我們?cè)诮榻B std::enable_if 的時(shí)候提到,如果 condition 不滿足的話,會(huì)生成一個(gè)無(wú)效的類型,此處由于SFINAE 機(jī)制的存在,只要 call 存在一個(gè)匹配的話,就不會(huì)報(bào)錯(cuò)(只是簡(jiǎn)單的丟棄該函數(shù))。

std::enable_if<>的實(shí)現(xiàn)機(jī)制如下代碼所示:

template<bool Cond, typename T = void> struct enable_if {};template<typename T> struct enable_if<true, T> { typedef T type; };123123

從上面的代碼可以看到

在 condition 為真的時(shí)候,由于偏特化機(jī)制,第二個(gè)結(jié)構(gòu)體模板明顯是一個(gè)更好的匹配,所以 std::enable_if<>::type 就是有效的。

當(dāng) condition 為假的時(shí)候,只有第一個(gè)結(jié)構(gòu)體模板能夠匹配,所以std::enable_if<>::type 是無(wú)效的,會(huì)被丟棄,編譯器會(huì)報(bào)錯(cuò):error: no type named ‘type’ in ‘struct std::enable_if<false, bool>。

Note: 下面是Visual Studio 2013的實(shí)現(xiàn):

    // TEMPLATE CLASS enable_iftemplate<bool _Test,    class _Ty = void>    struct enable_if    {   // type is undefined for assumed !_Test    };template<class _Ty>    struct enable_if<true, _Ty>    {   // type is _Ty for _Test    typedef _Ty type;    };123456789101112123456789101112

std::enable_if<> 使用及使用

std::enable_if<> 的使用原型如下所示:

template <bool Cond, class T = void> struct enable_if;11Cond, A compile-time constant of type boolT, A type.

使用 enable_if 的時(shí)候,對(duì)參數(shù)有這兩方面的限制。

member typedefinition
typeT (defined only if Cond is true)

該例子來(lái)自于 這里:

// enable_if example: two ways of using enable_if#include <iostream>#include <type_traits>// 1. the return type (bool) is only valid if T is an integral type:template <class T>typename std::enable_if<std::is_integral<T>::value,bool>::type  is_odd (T i) {return bool(i%2);}// 2. the second template argument is only valid if T is an integral type:template < class T,           class = typename std::enable_if<std::is_integral<T>::value>::type>bool is_even (T i) {return !bool(i%2);}int main() {  short int i = 1;    // code does not compile if type of i is not integral  std::cout << std::boolalpha;  std::cout << "i is odd: " << is_odd(i) << std::endl;  std::cout << "i is even: " << is_even(i) << std::endl;  return 0;}123456789101112131415161718192021222324123456789101112131415161718192021222324頂
發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 通许县| 成武县| 奉化市| 黎城县| 荆门市| 蒙城县| 武平县| 阿拉善左旗| 永川市| 连州市| 河南省| 色达县| 安化县| 廊坊市| 吉水县| 长葛市| 大埔区| 墨竹工卡县| 香格里拉县| 靖州| 井陉县| 怀柔区| 汶川县| 莒南县| 武义县| 云南省| 阿拉善右旗| 乌什县| 石城县| 曲麻莱县| 乌苏市| 宁海县| 福清市| 炎陵县| 华亭县| 张掖市| 五指山市| 岚皋县| 万安县| 青神县| 肇源县|