std::enable_if

keywords

  1. std::enable_if

0 引言

c++ 學(xué)習(xí)筆記 之 c++11 新特性:std::enable_if

1 std::enable_if的概述

std::enable_if,滿足條件時(shí)類型有效。 我們結(jié)合源碼來(lái)看看(位于 type_traits 中)

// Primary template.
/// Define a member typedef @c type only if a boolean constant is true.
template<bool, typename _Tp = void>
  struct enable_if
  { };

// Partial specialization for true.
template<typename _Tp>
  struct enable_if<true, _Tp>
  { typedef _Tp type; };

從上面源碼可以看到,只有第一個(gè)模板參數(shù)為true時(shí),struct 才會(huì)定義一個(gè)public的type類型(struct成員默認(rèn)是public類型),type即為第二個(gè)模板參數(shù)

下面看看這幾個(gè)定義

std::enable_if<true, int>::type t; // OK,定義了一個(gè)變量t,類型是int
std::enable_if<false, int>::type t2 // FAIL,因?yàn)闆](méi)有type這個(gè)類型,編譯失敗
std::enable_if<true>::type; // OK, 第一模板參數(shù)是true,第二模板參數(shù)是通常版本中定義的默認(rèn)類型即void

那么std::enable_if 有什么用呢?

2 std::enable_if 的使用場(chǎng)景

參考 cppreference.com std::enable_if 的說(shuō)明文檔,總結(jié)幾個(gè)使用場(chǎng)景如下

2.1 類型偏特化

看看下面案例

關(guān)于偏特化的知識(shí)點(diǎn),后面專門分析

#include <iostream>
template<class T, class Enable = void>
class A {
 public:
  A() { std::cout << "primary template\r\n"; }
}; // primary template

template<class T>
class A<T, typename std::enable_if<std::is_floating_point<T>::value>::type> {
 public:
  A() { std::cout << "partial specialization\r\n"; }
}; // specialization for floating point types

int main() {
  std::shared_ptr<A<int>> a1 = std::make_shared<A<int>>();
  auto a2 = std::make_shared<A<double>>();
}

輸出如下

primary template
partial specialization

從上面案例可以看到,可以通過(guò)std::enable_if,控制不同的數(shù)據(jù)類型,選擇不同的類模板

2.2 函數(shù)返回值場(chǎng)景

通過(guò)函數(shù)的返回值,控制不同的條件下,選擇不同的模板。直接看看下面代碼案例

#include <iostream>

// enabled via the return type
template<class T>
typename std::enable_if<std::is_trivially_default_constructible<T>::value>::type
construct(T *) {
  std::cout << "default constructing trivially default constructible T\n";
}
template<class T>
typename std::enable_if<!std::is_trivially_default_constructible<T>::value>::type
construct(T *p) {
  std::cout << "default constructing non-trivially default constructible T\n";
}

int main() {
  int a = 1;
  std::string str = "hell";
  construct(&a);
  construct(&str);
  return 0;
}

輸出如下

default constructing trivially default constructible T
default constructing non-trivially default constructible T

2.3 函數(shù)參數(shù)場(chǎng)景

通過(guò)函數(shù)的參數(shù),控制不同的條件下,選擇不同的模板。看看下面案例

#include <iostream>

// enabled via a parameter
template<class T>
void destroy(T *,
    typename std::enable_if<std::is_trivially_destructible<T>::value>::type * = 0) {
  std::cout << "destroying trivially destructible T\n";
}

// enabled via a non-type template parameter
template<class T, typename std::enable_if<!std::is_trivially_destructible<T>{} &&
            (std::is_class<T>{} || std::is_union<T>{}),bool>::type = true>
void destroy(T* t)
{
  std::cout << "destroying non-trivially destructible T\n";
}

int main() {
  int a = 1;
  std::string str = "hell";
  destroy(&a);
  destroy(&str);
  return 0;
}

輸出如下:

destroying trivially destructible T
destroying non-trivially destructible T

上面參考官方文檔列舉了幾個(gè)使用場(chǎng)景。 后面會(huì)根據(jù)實(shí)際應(yīng)用補(bǔ)充場(chǎng)景以及理解。

99 拓展

在官方的介紹文檔里面,提到了SFINAE(Substitution failure is not an error),下面簡(jiǎn)單介紹下這個(gè)概念,先看看下面代碼

#include <iostream>
struct B { typedef int type; };

template<class T>
typename T::type h(typename B::type) { std::cout << "h special\r\n"; }
template<class T>
void h(T t) { std::cout << "h common\r\n"; }

int main() {
  h<B>(10);
  h<int>(10);
  return 0;
}

輸出為

h special
h common

上面就是官方的代碼,我簡(jiǎn)化了下。 從上面輸出看,兩個(gè)函數(shù)調(diào)用都正確推導(dǎo)到了各自的函數(shù)模板。SFINAE 就是如果推導(dǎo)模板函數(shù)可以找到一個(gè)正確的版本,過(guò)程中即使存在模板匹配時(shí)的語(yǔ)法錯(cuò)誤,編譯器也不會(huì)報(bào)錯(cuò),比如上述的 int::type,是存在語(yǔ)法錯(cuò)誤的


支持原創(chuàng),轉(zhuǎn)載請(qǐng)附上原文鏈接


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容