日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

Boost Part III. 函数对象与高级编程 Library 10. Lambda 用法

發(fā)布時(shí)間:2025/3/21 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Boost Part III. 函数对象与高级编程 Library 10. Lambda 用法 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.


讓你的函數(shù)對(duì)象可以與Boost.Lambda 一起使用

不是所有的表達(dá)式都適合使用 lambda 表達(dá)式,復(fù)雜的表達(dá)式更適合使用普通的函數(shù)對(duì)象,而且會(huì)多次重用的表達(dá)式也應(yīng)該成為你代碼中的一等公民。它們應(yīng)該被收集為一個(gè)可重用函數(shù)對(duì)象的庫(kù)。但是, 你也可能想把這些函數(shù)對(duì)象用在lambda 表達(dá)式中,你希望它們可以與 Lambda 一起使用;不是所有函數(shù)對(duì)象都能做到。問題是函數(shù)對(duì)象的返回類型不能象普通函數(shù)那樣被推斷出來(lái);這是語(yǔ)言的固有限制。但是,有一個(gè)定義好的方法來(lái)把這個(gè)重 要的信息提供給Lambda 庫(kù),以使得 bind 表達(dá)式更加干凈。作為這個(gè)問題的一個(gè)例子,我們看以下函數(shù)對(duì)象:

template <typename T> class add_prev {T prev_; public:add_prev() : prev_(0){}T operator()(T t) {prev_+=t;return prev_;} };

對(duì)于這樣一個(gè)函數(shù)對(duì)象,lambda 表達(dá)式不能推斷出返回類型,因此以下例子不能編譯。

#include <iostream> #include <algorithm> #include <vector> #include "boost/lambda/lambda.hpp" #include "boost/lambda/bind.hpp" int main() {using namespace boost::lambda;std::vector<int> vec;vec.push_back(5);vec.push_back(8);vec.push_back(2);vec.push_back(1);add_prev<int> ap;std::transform(vec.begin(),vec.end(),vec.begin(),bind(var(ap),_1)); }

問題在于對(duì) transform 的調(diào)用。

std::transform(vec.begin(),vec.end(),vec.begin(),bind(var(ap),_1));

當(dāng)綁定器被實(shí)例化時(shí),返回類型推斷的機(jī)制被使用…而且失敗了。因此,這段程序不能通過編譯,你必須顯式地告訴 bind 返回類型是什么,象這樣:

std::transform(vec.begin(),vec.end(),vec.begin(),bind<int>(var(ap),_1));

這是為 lambda 表達(dá)式顯式設(shè)置返回類型的正常格式的縮寫,它等價(jià)于這段代碼。

std::transform(vec.begin(),vec.end(),vec.begin(),ret<int>(bind<int>(var(ap),_1)));

這并不是什么新問題;對(duì)于在標(biāo)準(zhǔn)庫(kù)算法中使用函數(shù)對(duì)象都有同樣的問題。在標(biāo)準(zhǔn)庫(kù)中,解決的方法是增加typedefs 來(lái)表明函數(shù)對(duì)象的返回類型及參數(shù)類型。標(biāo)準(zhǔn)庫(kù)還提供了助手類來(lái)完成這件事,即類模板unary_function binary_function,要讓我們的例子類add_prev 成為合適的函數(shù)對(duì)象,可以通過定義所需的 typedefs (對(duì)于一元函數(shù)對(duì)象,是argument_type result_type,對(duì)于二元函數(shù)對(duì)象,是first_argument_type,second_argument_type, result_type),也可以通過派生自unary_function/binary_function 來(lái)實(shí)現(xiàn)。

template <typename T> class add_prev : public std::unary_function<T,T>

這對(duì)于lambda 表達(dá)式是否也足夠好了呢?我們可以簡(jiǎn)單地復(fù)用這種方法以及我們已有的函數(shù)對(duì)象嗎?唉,答案是否定的。這種typedef 方法有一個(gè)問題:對(duì)于泛化的調(diào)用操作符,當(dāng)返回類型或參數(shù)類型依賴于模板參數(shù)時(shí)會(huì)怎么樣?或者,當(dāng)存在多個(gè)重載的調(diào)用操作符時(shí)會(huì)怎么樣?由于語(yǔ)言支持模板的typedefs, 這些問題可以解決,但是現(xiàn)在不是這樣的。這就是為什么 Boost.Lambda 需要一個(gè)不同的方法,即一個(gè)名為 sig 的嵌套泛型類。為了讓返回類型推斷可以和add_prev 一起使用,我們象下面那樣定義一個(gè)嵌套類型 sig

template <typename T> class add_prev :public std::unary_function<T,T> {T prev_; public:template <typename Args> class sig {public:typedef T type;}; // Rest of definition

模板參數(shù) Args 實(shí)際上是一個(gè) tuple,包含了函數(shù)對(duì)象(第一個(gè)元素)和調(diào)用操作符的參數(shù)類型。在這個(gè)例子中,我們不需要這些信息,返回類型和參數(shù)類型都是T. 使用這個(gè)改進(jìn)版本的 add_prev,再不需要在 lambda 表達(dá)式中使用返回類型推斷的縮寫,因此我們最早那個(gè)版本的代碼現(xiàn)在可以編譯了。

std::transform(vec.begin(),vec.end(),vec.begin(),bind(var(ap),_1));

我們?cè)賮?lái)看看tuple 作為 sig 的模板參數(shù)是如何工作的,來(lái)看另一個(gè)有兩個(gè)調(diào)用操作符的函數(shù)對(duì)象,其中一個(gè)版本接受一個(gè)int 參數(shù),另一個(gè)版本接受一個(gè) const std::string引用。我們必須要解決的問題是,"如果傳遞給 sig模板的 tuple 的第二個(gè)元素類型為 int,則設(shè)置返回類型為 std::string; 如果傳遞給 sig 模板的 tuple 的第二個(gè)元素類型為 std::string, 則設(shè)置返回類型為 double"。為此,我們?cè)黾右粋€(gè)類模板,我們可以對(duì)它進(jìn)行特化并在add_prev::sig 中使用它。

template <typename T> class sig_helper {}; // The version for the overload on int template<> class sig_helper<int> { public:typedef std::string type; }; // The version for the overload on std::string template<> class sig_helper<std::string> { public:typedef double type; }; // The function object class some_function_object {template <typename Args> class sig {typedef typename boost::tuples::element<1,Args>::typecv_first_argument_type;typedef typenameboost::remove_cv<cv_first_argument_type>::typefirst_argument_type;public:// The first argument helps us decide the correct versiontypedef typenamesig_helper<first_argument_type>::type type;};std::string operator()(int i) const {std::cout << i << '\n';return "Hello!";}double operator()(const std::string& s) const {std::cout << s << '\n';return 3.14159265353;} };

這里有兩個(gè)重要的部分要討論:首先是助手類sig_helper, 它由類型 T特化。這個(gè)類型可以是 int std::string,依賴于要使用哪一個(gè)重載版本的調(diào)用操作符。通過對(duì)這個(gè)模板進(jìn)行全特化,來(lái)定義正確的 typedeftype。第二個(gè)要注意的部分是 sig 類,它的第一個(gè)參數(shù)(tuple 的第二個(gè)元素)被取出,并去掉所有的 const volatile 限定符,結(jié)果類型被用于實(shí)例化正確版本的sig_helper 類,后者具有正確的 typedef type.這是為我們的類定義返回類型的一種相當(dāng)復(fù)雜(但是必須!)的方法,但是多數(shù)情況下,通常都只有一個(gè)版本的調(diào)用操作符;所以正確地增加嵌套sig 類是一件普通的工作。

我們的函數(shù)對(duì)象可以在 lambda 表達(dá)式中正確使用是很重要的,在需要時(shí)定義嵌套sig 類是一個(gè)好主意;它很有幫助。

附代碼:

#include <iostream> #include <algorithm> #include <vector> #include <string> #include "boost/lambda/lambda.hpp" #include "boost/lambda/bind.hpp" template <typename T> class sig_helper {}; // The version for the overload on int template<> class sig_helper<int> { public:typedef std::string type; }; // The version for the overload on std::string template<> class sig_helper<std::string> { public:typedef double type; }; // The function object class some_function_object {template <typename Args> class sig {typedef typename boost::tuples::element<1, Args>::typecv_first_argument_type;typedef typenameboost::remove_cv<cv_first_argument_type>::typefirst_argument_type;public:// The first argument helps us decide the correct versiontypedef typenamesig_helper<first_argument_type>::type type;}; public:std::string operator()(int i) const {std::cout << i << '\n';return "Hello!";}double operator()(const std::string& s) const {std::cout << s << '\n';return 3.14159265353;} }; template <typename T, typename Operation> void for_all(T& t, Operation Op) {std::for_each(t.begin(), t.end(), Op); } template <typename T> void print(std::vector<T>& vec) {//using namespace boost::lambda;for_all(vec, std::cout << boost::lambda::_1 << '\n'); } int main() {using namespace boost::lambda;{std::vector<std::string> vec;vec.push_back("my darling");vec.push_back("so sweet...");std::vector<double> vec2;vec2.push_back(1);vec2.push_back(2);some_function_object sfo;std::transform(vec.begin(),vec.end(),vec2.begin(),bind(var(sfo), _1));print(vec2);}{std::vector<std::string> vec;vec.push_back("my darling");vec.push_back("so sweet...");std::vector<int> vec2;vec2.push_back(1);vec2.push_back(2);some_function_object sfo;std::transform(vec2.begin(),vec2.end(),vec.begin(),bind(var(sfo), _1));print(vec);} }

總結(jié)

以上是生活随笔為你收集整理的Boost Part III. 函数对象与高级编程 Library 10. Lambda 用法的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 不卡av免费在线观看 | 五月天福利视频 | 国产午夜视频 | 中文字幕在线视频免费播放 | 精品一区二区免费视频 | 亚洲一级一区 | 国产sss| 日本在线 | 一本久久久久 | 精品777| 亚洲精品一区二区三区新线路 | 精品在线播放 | 国产精品一区二区免费在线观看 | 老熟妇一区二区三区啪啪 | 五月丁香花 | 国产农村妇女毛片精品久久麻豆 | 麻豆视频入口 | 久久午夜夜伦鲁鲁片 | 欧美成人午夜 | 爱情岛论坛成人av | 日本不卡一区二区三区 | 日韩电影网址 | 久久嫩| 天天操天天添 | 人人爽久久涩噜噜噜网站 | 国产sm在线观看 | 国产精品美女主播 | 中文字幕亚洲第一 | 国内一区二区三区 | av在线不卡网 | 调教在线观看 | h片观看| 久久夜夜操妹子 | 黄色a在线| 色女人在线 | 超碰综合 | 色呦呦在线看 | 成人国产精品免费观看动漫 | 51调教丨国产调教视频 | 成人日b视频 | 国产精品久久久久久免费观看 | 日韩av无码中文字幕 | 亚洲精品一区 | 看片网址国产福利av中文字幕 | 亚洲国产综合av | 日韩欧美在线观看一区 | 日批网站在线观看 | 99久久精品国产亚洲 | 久久日本视频 | 欧美日韩在线一区二区 | 女女h百合无遮羞羞漫画软件 | 天天插天天狠 | 久久99操 | 富婆如狼似虎找黑人老外 | 97操 | 95看片淫黄大片一级 | 国模人体一区二区 | 天堂网视频在线 | 国产午夜精品久久久久久久久久 | 欧美性生交xxxxx久久久 | 亚洲精品视频在线免费 | 美国黄色一级视频 | 精品免费在线视频 | 国产伦精品一区二区三区精品 | 涩涩五月天 | 欧美一卡二卡在线 | 成人一区二区视频 | 丝袜淫脚| 老太太av | 在线观看国产一区二区三区 | 性感美女一级片 | 国产精品第9页 | 亚洲av综合av一区二区三区 | 深夜影院深a | 看黄色一级大片 | av福利网站 | 日韩av大全 | 在线亚洲人成电影网站色www | 天天透天天干 | 久久99一区二区 | 少妇无内裤下蹲露大唇视频 | 亚洲欧美韩国 | 欧美性网站 | av观看网站 | 国精产品一区一区三区 | 色视av| 影音先锋美女 | 狠狠91 | 青青草国产在线播放 | 韩国裸体网站 | 一区免费在线观看 | 九九热国产视频 | 国产传媒国产传媒 | 91精品国产色综合久久不卡98 | 成人免费看类便视频 | 欧美大片免费 | 欧美人体做爰大胆视频 | 自拍偷拍第| 青青国产精品视频 |