最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C++ Boost Phoenix庫示例分析使用

 更新時間:2022年11月14日 16:59:03   作者:無水先生  
Boost是為C++語言標準庫提供擴展的一些C++程序庫的總稱。Boost庫是一個可移植、提供源代碼的C++庫,作為標準庫的后備,是C++標準化進程的開發(fā)引擎之一,是為C++語言標準庫提供擴展的一些C++程序庫的總稱

一、說明

在函數式編程模型中,函數是對象,與其他對象一樣,可以作為參數傳遞給函數或存儲在容器中。有許多支持函數式編程模型的 Boost 庫。

  • Boost.Phoenix 是這些庫中最廣泛、也是最重要的庫。它取代了庫 Boost.Lambda,它被簡要介紹,但只是為了完整性。
  • Boost.Function 提供了一個類,可以輕松定義函數指針,而無需使用源自 C 編程語言的語法。
  • Boost.Bind 是一個適配器,即使實際簽名與預期簽名不同,它也允許您將函數作為參數傳遞給其他函數。
  • Boost.Ref 可用于傳遞對對象的引用,即使函數通過副本傳遞參數。
  • Boost.Lambda 可以稱為 Boost.Phoenix 的前身。它是一個相當古老的庫,并且在將 C++11 添加到編程語言之前很多年就允許使用 lambda 函數。

二、預先知道Boost.Phoenix

Boost.Phoenix 是函數式編程最重要的 Boost 庫。雖然 Boost.Bind 或 Boost.Lambda 等庫為函數式編程提供了一些支持,但 Boost.Phoenix 包含這些庫的功能并超越了它們。

在函數式編程中,函數是對象,可以像對象一樣處理。使用 Boost.Phoenix,一個函數可以返回另一個函數作為結果。也可以將一個函數作為參數傳遞給另一個函數。因為函數是對象,所以可以區(qū)分實例化和執(zhí)行。訪問一個函數不等于執(zhí)行它。

Boost.Phoenix 支持使用函數對象進行函數式編程:函數是基于類的對象,這些類重載了運算符 operator()。這樣,函數對象的行為就像 C++ 中的其他對象一樣。例如,它們可以被復制并存儲在容器中。但是,它們的行為也類似于函數,因為它們可以被調用。

函數式編程在 C++ 中并不新鮮。您可以將一個函數作為參數傳遞給另一個函數,而無需使用 Boost.Phoenix。

三、示例和代碼

示例 39.1。謂詞作為全局函數、lambda 函數和 Phoenix 函數

#include <boost/phoenix/phoenix.hpp>
#include <vector>
#include <algorithm>
#include <iostream>
bool is_odd(int i) { return i % 2 == 1; }
int main()
{
  std::vector<int> v{1, 2, 3, 4, 5};
  std::cout << std::count_if(v.begin(), v.end(), is_odd) << '\n';
  auto lambda = [](int i){ return i % 2 == 1; };
  std::cout << std::count_if(v.begin(), v.end(), lambda) << '\n';
  using namespace boost::phoenix::placeholders;
  auto phoenix = arg1 % 2 == 1;
  std::cout << std::count_if(v.begin(), v.end(), phoenix) << '\n';
}

Example39.1

示例 39.1 使用算法 std::count_if() 來計算向量 v 中的奇數。std::count_if() 被調用 3 次,一次使用謂詞作為獨立函數,一次使用 lambda 函數,一次使用鳳凰功能。

Phoenix 函數與獨立函數和 lambda 函數不同,因為它沒有框架。雖然其他兩個函數有一個帶有簽名的函數頭,但 Phoenix 函數似乎只包含一個函數體。

Phoenix 函數的關鍵組件是 boost::phoenix::placeholders::arg1。 arg1 是函數對象的全局實例。您可以像 std::cout 一樣使用它:一旦包含相應的頭文件,這些對象就會存在。

arg1 用于定義一元函數。表達式 arg1 % 2 == 1 創(chuàng)建一個需要一個參數的新函數。該函數不會立即執(zhí)行,而是存儲在 Phoenix 中。 phoenix 被傳遞給 std::count_if() ,它為 v 中的每個數字調用謂詞。

arg1 是調用 Phoenix 函數時傳遞的值的占位符。由于此處僅使用了 arg1,因此創(chuàng)建了一個一元函數。 Boost.Phoenix 提供了額外的占位符,例如 boost::phoenix::placeholders::arg2 和 boost::phoenix::placeholders::arg3。 Phoenix 函數總是期望與具有最大數量的占位符一樣多的參數。

Example39.1

示例 39.1 將 3 寫入標準輸出 3 次。

示例 39.2。 Phoenix 函數與 lambda 函數

#include <boost/phoenix/phoenix.hpp>
#include <vector>
#include <algorithm>
#include <iostream>
int main()
{
  std::vector<int> v{1, 2, 3, 4, 5};
  auto lambda = [](int i){ return i % 2 == 1; };
  std::cout << std::count_if(v.begin(), v.end(), lambda) << '\n';
  std::vector<long> v2;
  v2.insert(v2.begin(), v.begin(), v.end());
  using namespace boost::phoenix::placeholders;
  auto phoenix = arg1 % 2 == 1;
  std::cout << std::count_if(v.begin(), v.end(), phoenix) << '\n';
  std::cout << std::count_if(v2.begin(), v2.end(), phoenix) << '\n';
}

Example39.2

例 39.2 強調了 Phoenix 和 lambda 函數之間的一個關鍵區(qū)別。除了不需要帶有參數列表的函數頭之外,Phoenix 函數參數沒有類型。 lambda 函數 lambda 需要一個 int 類型的參數。 Phoenix 函數 phoenix 將接受模運算符可以處理的任何類型。

將 Phoenix 函數視為函數模板。像函數模板一樣,Phoenix 函數可以接受任何類型。這使得在示例 39.2 中可以使用 phoenix 作為容器 v 和 v2 的謂詞,即使它們存儲不同類型的數字。如果您嘗試將謂詞 lambda 與 v2 一起使用,則會出現編譯器錯誤。

示例 39.3。 Phoenix 用作延遲 C++ 代碼

#include <boost/phoenix/phoenix.hpp>
#include <vector>
#include <algorithm>
#include <iostream>
int main()
{
  std::vector<int> v{1, 2, 3, 4, 5};
  using namespace boost::phoenix::placeholders;
  auto phoenix = arg1 > 2 && arg1 % 2 == 1;
  std::cout << std::count_if(v.begin(), v.end(), phoenix) << '\n';
}

Example39.3

示例 39.3 使用 Phoenix 函數作為謂詞,使用 std::count_if() 計算大于 2 的奇數。Phoenix 函數訪問 arg1 兩次:一次測試占位符是否大于 2,一次測試它是否為奇數.條件與 && 相關聯(lián)。

您可以將 Phoenix 函數視為不會立即執(zhí)行的 C++ 代碼。示例 39.3 中的 Phoenix 函數看起來像一個使用多個邏輯和算術運算符的條件。但是,條件不會立即執(zhí)行。它僅在從 std::count_if() 中訪問時執(zhí)行。 std::count_if() 中的訪問是正常的函數調用。

示例 39.3 將 2 寫入標準輸出。

示例 39.4。顯式 Phoenix 類型

#include <boost/phoenix/phoenix.hpp>
#include <vector>
#include <algorithm>
#include <iostream>
int main()
{
  std::vector<int> v{1, 2, 3, 4, 5};
  using namespace boost::phoenix;
  using namespace boost::phoenix::placeholders;
  auto phoenix = arg1 > val(2) && arg1 % val(2) == val(1);
  std::cout << std::count_if(v.begin(), v.end(), phoenix) << '\n';
}

Example39.4

例 39.4 對 Phoenix 函數中的所有操作數使用顯式類型。嚴格來說,你看不到類型,只有輔助函數 boost::phoenix::val()。此函數返回使用傳遞給 boost::phoenix::val() 的值初始化的函數對象。函數對象的實際類型無關緊要。重要的是 Boost.Phoenix 為不同類型重載了運算符,如 >、&&、% 和 ==。因此,不會立即檢查條件。相反,函數對象被組合以創(chuàng)建更強大的函數對象。根據操作數,它們可能會自動用作函數對象。否則,您可以調用 val() 等輔助函數。

示例 39.5。 boost::phoenix::placeholders::arg1 和 boost::phoenix::val()

#include <boost/phoenix/phoenix.hpp>
#include <iostream>
int main()
{
  using namespace boost::phoenix::placeholders;
  std::cout << arg1(1, 2, 3, 4, 5) << '\n';
  auto v = boost::phoenix::val(2);
  std::cout << v() << '\n';
}

Example39.5

示例 39.5 說明了 arg1 和 val() 如何工作。 arg1 是函數對象的實例。它可以直接使用,也可以像函數一樣調用。您可以傳遞任意數量的參數——arg1 返回第一個參數。

val() 是一個用于創(chuàng)建函數對象實例的函數。函數對象使用作為參數傳遞的值進行初始化。如果實例像函數一樣被訪問,則返回該值。

示例 39.5 將 1 和 2 寫入標準輸出。

示例 39.6。創(chuàng)建自己的 Phoenix 函數

#include <boost/phoenix/phoenix.hpp>
#include <vector>
#include <algorithm>
#include <iostream>
struct is_odd_impl
{
    typedef bool result_type;
 
    template <typename T>
    bool operator()(T t) const { return t % 2 == 1; }
};
boost::phoenix::function<is_odd_impl> is_odd;
int main()
{
  std::vector<int> v{1, 2, 3, 4, 5};
  using namespace boost::phoenix::placeholders;
  std::cout << std::count_if(v.begin(), v.end(), is_odd(arg1)) << '\n';
}

Example39.6

示例 39.6 解釋了如何創(chuàng)建自己的 Phoenix 函數。您將函數對象傳遞給模板 boost::phoenix::function。該示例傳遞了 is_odd_impl 類。此類重載運算符 operator():當傳入奇數時,運算符返回 true。否則,運算符返回 false。

請注意,您必須定義類型result_type。 Boost.Phoenix 使用它來檢測運算符 operator() 的返回值的類型。

is_odd() 是一個可以像 val() 一樣使用的函數。兩個函數都返回一個函數對象。調用時,參數將轉發(fā)給運算符 operator()。對于示例 39.6,這意味著 std::count_if() 仍然計算奇數。

示例 39.7。將獨立功能轉換為 Phoenix 功能

#include <boost/phoenix/phoenix.hpp>
#include <vector>
#include <algorithm>
#include <iostream>
bool is_odd_function(int i) { return i % 2 == 1; }
BOOST_PHOENIX_ADAPT_FUNCTION(bool, is_odd, is_odd_function, 1)
int main()
{
  std::vector<int> v{1, 2, 3, 4, 5};
  using namespace boost::phoenix::placeholders;
  std::cout << std::count_if(v.begin(), v.end(), is_odd(arg1)) << '\n';
}

如果要將獨立函數轉換為 Phoenix 函數,可以按照示例 39.7 進行操作。您不必像前面的示例中那樣定義函數對象。

您可以使用宏 BOOST_PHOENIX_ADAPT_FUNCTION 將獨立函數轉換為 Phoenix 函數。將返回值的類型、要定義的 Phoenix 函數的名稱、獨立函數的名稱以及參數個數傳遞給宏。

示例 39.8。 Phoenix 使用 boost::phoenix::bind() 函數

#include <boost/phoenix/phoenix.hpp>
#include <vector>
#include <algorithm>
#include <iostream>
bool is_odd(int i) { return i % 2 == 1; }
int main()
{
  std::vector<int> v{1, 2, 3, 4, 5};
  using namespace boost::phoenix;
  using namespace boost::phoenix::placeholders;
  std::cout << std::count_if(v.begin(), v.end(), bind(is_odd, arg1)) << '\n';
}

要將獨立函數用作 Phoenix 函數,您還可以使用 boost::phoenix::bind(),如示例 39.8 中所示。 boost::phoenix::bind() 的工作方式類似于 std::bind()。獨立函數的名稱作為第一個參數傳遞。所有進一步的參數都被轉發(fā)到獨立功能。

小費
避免使用 boost::phoenix::bind()。創(chuàng)建您自己的 Phoenix 函數。這會導致代碼更具可讀性。尤其是對于復雜的表達式,處理 boost::phoenix::bind() 的額外細節(jié)是沒有幫助的。

示例 39.9。任意復雜的 Phoenix 函數

#include <boost/phoenix/phoenix.hpp>
#include <vector>
#include <algorithm>
#include <iostream>
int main()
{
  std::vector<int> v{1, 2, 3, 4, 5};
  using namespace boost::phoenix;
  using namespace boost::phoenix::placeholders;
  int count = 0;
  std::for_each(v.begin(), v.end(), if_(arg1 > 2 && arg1 % 2 == 1)
    [
      ++ref(count)
    ]);
  std::cout << count << '\n';
}

Boost.Phoenix 提供了一些模擬 C++ 關鍵字的函數對象。例如,您可以使用函數 boost::phoenix::if_()(參見示例 39.9)創(chuàng)建一個函數對象,該對象的行為類似于 if 并測試條件。如果條件為真,則使用 operator[] 傳遞給函數對象的代碼將被執(zhí)行。當然,該代碼也必須基于函數對象。這樣,您可以創(chuàng)建復雜的 Phoenix 函數。

示例 39.9 對每個大于 2 的奇數進行增量計數。要對 count 使用增量運算符,請使用 boost::phoenix::ref() 將 count 包裝在一個函數對象中。與 boost::phoenix::val() 相比,沒有值被復制到函數對象中。 boost::phoenix::ref() 返回的函數對象存儲了一個引用——這里是對 count 的引用。

小提示

不要使用 Boost.Phoenix 創(chuàng)建復雜的函數。最好使用 C++11 中的 lambda 函數。雖然 Boost.Phoenix 接近 C++ 語法,但使用 if_ 等關鍵字或方括號之間的代碼塊并不一定會提高可讀性。

到此這篇關于C++ Boost Phoenix庫示例分析使用的文章就介紹到這了,更多相關C++ Boost Phoenix庫內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • 判斷本機office安裝版本的方法分享

    判斷本機office安裝版本的方法分享

    這篇文章主要介紹了判斷本機office安裝版本的方法分享,需要的朋友可以參考下
    2014-01-01
  • C語言實現高精度加減法

    C語言實現高精度加減法

    這篇文章主要為大家詳細介紹了C語言實現高精度加減法,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-05-05
  • 關于C++友元函數的實現講解

    關于C++友元函數的實現講解

    今天小編就為大家分享一篇關于關于C++友元函數的實現講解,小編覺得內容挺不錯的,現在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2018-12-12
  • C語言實現班級檔案管理系統(tǒng)課程設計

    C語言實現班級檔案管理系統(tǒng)課程設計

    這篇文章主要為大家詳細介紹了C語言實現班級檔案管理系統(tǒng)課程設計,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-12-12
  • C++插入排序算法實例詳解

    C++插入排序算法實例詳解

    這篇文章主要為大家詳細介紹了C++插入排序算法實例,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-12-12
  • 教你用C語言實現三子棋

    教你用C語言實現三子棋

    這篇文章主要為大家詳細介紹了C語言實現簡單三子棋程序,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-11-11
  • C語言實現餐飲點餐管理系統(tǒng)

    C語言實現餐飲點餐管理系統(tǒng)

    這篇文章主要為大家詳細介紹了C語言實現餐飲點餐管理系統(tǒng),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-01-01
  • C++回溯算法中的全排列問題分析探討

    C++回溯算法中的全排列問題分析探討

    遞歸中遇到一個問題全排列的問題,我看見回溯特別神奇,特此記錄一下。對比一下深度優(yōu)先搜索與廣度優(yōu)先搜索,個人感覺這里的回溯像是一種遞歸樹中的深度優(yōu)先搜索的算法,他不斷構造往下延伸的深度,使其達到完全編列
    2023-03-03
  • 了解C++編程中指定的異常和未經處理的異常

    了解C++編程中指定的異常和未經處理的異常

    這篇文章主要介紹了C++中指定的異常和未經處理的異常,介紹了有關noexcept和terminate的作用,并結合了C++11標準的新特性,需要的朋友可以參考下
    2016-01-01
  • 一文帶你深入了解C++中的類型轉換

    一文帶你深入了解C++中的類型轉換

    在C語言中,如果賦值運算符左右兩側類型不同,或者形參與實參類型不匹配,或者返回值類型與接收返回值類型不一致時,就需要發(fā)生類型轉化。本文主要介紹了C++中常見的四個類型轉換,需要的可以參考一下
    2022-12-12

最新評論

房山区| 法库县| 资阳市| 察隅县| 慈溪市| 铁力市| 扎赉特旗| 汝南县| 襄垣县| 纳雍县| 怀安县| 平顺县| 盐城市| 玛曲县| 南漳县| 大余县| 汪清县| 海口市| 惠来县| 万安县| 太白县| 宜黄县| 古交市| 江都市| 汝阳县| 滕州市| 鄂伦春自治旗| 厦门市| 会宁县| 湘潭县| 慈溪市| 聊城市| 错那县| 鄂托克旗| 大港区| 丹东市| 武隆县| 通江县| 邵东县| 乌兰县| 林州市|