C++ Lambda表達式第一篇, 閉合(Closuretype)

C++ Lambda表達式第一篇, 閉合Closuretype

  • ClosureType::operator()(params)
    • auto 模板參數類型
    • 顯式模板參數類型
    • 其他
  • ClosureType::operator ret(*)(params)()

lambda 表達式是唯一的未命名,非聯合,非聚合類類型(稱為閉包類型)的純右值表達式,它在包含 lambda 的最小塊作用域、類作用域或命名空間作用域中聲明(出于 ADL 的目的)表達。

當且僅當 captures 為空時,閉包類型才是結構類型。

閉包類型具有以下成員,它們不能顯式實例化、顯式專門化或在友元聲明中命名:

ClosureType::operator()(params)

ret operator()(params) { body }
template<template-params>
ret operator()(params) { body }

調用時,執行 lambda 表達式的主體。訪問變量時,訪問其捕獲的副本(對于通過副本捕獲的實體)或原始對象(對于通過引用捕獲的實體)。

如果提供了operator()的參數列表,則為params,否則參數列表為空。

operator()的返回類型是trailing-type中指定的類型。

如果未提供 Trailing-type,則自動推導出operator() 的返回類型。

除非在 lambda 說明符中使用關鍵字 mutable,或者存在顯式對象參數,否則 operator() 的 cv 限定符為 const,并且通過 copy 捕獲的對象從內部不可修改這個運算符()。不允許顯式 const 限定符。 operator() 從來都不是虛擬的,并且不能具有 volatile 限定符。

  • 如果operator() 滿足constexpr 函數的要求,則它始終是constexpr。如果 lambda 說明符中使用了關鍵字 constexpr,那么,它也是 constexpr。
  • 如果 lambda 說明符中使用了關鍵字 consteval,則operator() 是立即函數。
  • 如果 lambda 說明符中使用了關鍵字 static,則operator() 是靜態成員函數。
  • 如果 params 包含顯式對象參數,則operator() 是顯式對象成員函數。

auto 模板參數類型

對于 params 中類型指定為 auto 的每個參數,都會按照出現的順序將發明的模板參數添加到 template-params 中。如果params對應的函數成員是函數參數包,則本發明的模板參數可以是參數包。

#include  <iostream>
#include  <iostream>
#include  <fstream>using namespace std;// generic lambda, operator() is a template with two parameters
auto glambda = [](auto a, auto&& b) { return a < b; };// generic lambda, operator() is a template with one parameter
auto vglambda = [](auto printer)
{return [=](auto&&... ts) // generic lambda, ts is a parameter pack{ printer(forward<decltype(ts)>(ts)...);// nullary lambda (takes no parameters):return [=] { printer(ts...); };};
};auto p = vglambda([](auto v1, auto v2, auto v3)
{cout << v1 << " " << v2 << " " << v3 << endl;
});int main() {	int   x = 100;bool b = glambda(3, (x / 10) - 3.14);cout << b << endl;b = glambda(3, (x / 20) - 3.14);cout << b << endl;auto q = p(1, 'a', 3.14); // outputs 1 a 3.14q();                      // outputs 1 a 3.14auto pp = vglambda(printf);pp("%s %d \n", "Sam", 45);
}

代碼運行的屏幕輸出

1
0
1 a 3.14
1 a 3.14
Sam 45

顯式模板參數類型

如果 lambda 定義使用顯式模板參數列表,則該模板參數列表將與 operator() 一起使用。對于 params 中類型指定為 auto 的每個參數,一個新的模板參數類型,將作為該模板參數列表的類型,直至到參數列表的末尾:

#include  <iostream>
#include  <iostream>
#include  <fstream>using namespace std;struct A
{A(int&& n) { cout << "rvalue overload, n=" << n << '\n'; }A(int& n)  { cout << "lvalue overload, n=" << n << '\n'; }
};class foo
{
public:template<class T1, class T2, class T3>foo(T1&& t1, T2&& t2, T3&& t3) :a1_{forward<T1>(t1)},a2_{forward<T2>(t2)},a3_{forward<T3>(t3)}{}private:A a1_, a2_, a3_;
};// generic lambda, operator() is a template with two parameters
auto glambda = []<class T>(T a, auto&& b) { return a < b; };// generic lambda, operator() is a template with one parameter pack
auto f1 = []<typename... Ts>(Ts&&... ts)
{return foo(forward<Ts>(ts)...);
};int main() {	int   x = 100;bool b = glambda(3, (x / 10) - 3.14);cout << b << endl;b = glambda(5.0, (x / 20) - 3.14);cout << b << endl;f1(1, 2, 4);
}
1
0
rvalue overload, n=1
rvalue overload, n=2
rvalue overload, n=4

其他

lambda 表達式上的異常規范exception適用于operator()。

為了名稱查找、確定 this 指針的類型和值,以及訪問非靜態類成員,閉包類型的operator() 的主體可以認為是 lambda 表達式的一部分。

struct X
{int x, y;int operator()(int);void f(){// 下面的lambda表達式是成員函數 X::f[=]() -> int{return operator()(this->x + y); // X::operator()(this->x + (*this).y)// this has type X*};}
};

ClosureType::operator ret(*)(params)()

- 無捕獲,非常規Lambda* using F = ret(*)(params);  operator F() const noexcept;* using F = ret(*)(params);* constexpr operator F() const noexcept;
- 無捕獲,常規lambda* template<template-params>operator fptr_t<template-params>() const noexcept;* template<template-params>constexpr operator fptr_t<template-params>() const noexcept;

僅當 lambda 表達式的捕獲列表為空時,才會定義此用戶定義的轉換函數。該函數是一個閉合對象的成員函數, 而且具有public, constexpr, 非虛、非顯式 和 const noexcept特征。

如果函數調用運算符是立即函數,則此函數是立即函數。

通用的無捕獲 lambda 具有一個用戶定義的轉換函數模板,它具有與 operator() 相同的新模板參數表。

#include  <iostream>using namespace std;void f1(int (*f)(int)) {int x = f(2);cout << "f=" << x << endl;
}void f2(char (*)(int)) {}
void h(int (*h)(int)) {  // #1int x = h(3);cout << "h=" << x << endl;
}void h(char (*)(int)) {} // #2auto glambda = [](auto a) { return a; };int& (*fpi)(int*) = [](auto* a) -> auto& { return *a; }; // OKint main()
{f1(glambda); // OK
//	auto y = f2(glambda); // error: not convertibleh(glambda);  // OK: calls #1 since #2 is not convertibleauto x = glambda(1);cout << "x: " << x << endl;auto y = fpi(&x);cout << "y: " << y << endl;
}

轉換函數的返回值是一個指向具有 C++ 語言鏈接的函數指針,調用該函數時,與在閉包類型的默認構造實例上調用閉包類型的函數調用運算符具有相同的效果。

轉換函數(模板)返回的值是一個指向具有 C++ 語言鏈接的函數的指針,調用該函數時,具有與以下相同的效果:

對于非泛型 lambda,在閉包類型的默認構造實例上調用閉包類型的operator()。
對于泛型 lambda,在閉包類型的默認構造實例上調用泛型 lambda 相應的operator() 特化。
轉換函數(模板)返回的值為

如果operator()是靜態的,則為具有C++語言鏈接的指向該operator()的指針,
否則,指向具有 C++ 語言鏈接的函數的指針,在調用該函數時,具有與以下相同的效果:
對于非泛型 lambda,在閉包類型的默認構造實例上調用閉包類型的operator()。
對于泛型 lambda,在閉包類型的默認構造實例上調用泛型 lambda 相應的operator() 特化。

如果函數調用運算符為 constexpr,則此函數為 constexpr。

#include  <iostream>using namespace std;auto Fwd = [](int(*fp)(int), auto a) { return fp(a); };
auto C = [](auto a) { return a; };auto NC = [](auto a) { static int s; return a; };int main() {	static_assert(Fwd(C, 3) == 3);//	static_assert(Fwd(NC, 3) == 3); // error: no specialization can be constexpr because of static s
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/43034.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/43034.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/43034.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【實習問題記錄】Nodeclub本地部署

問題描述 在按照官方網站給出的教程一步一步操作以后發現出現以下報錯&#xff1a; 問題分析 顯示連接不上mongodb&#xff0c;分析報錯可能是因為版本不匹配導致的&#xff0c;查看安裝的mongodb版本發現是7.0.4&#xff0c;與目標版本不匹配&#xff0c;同時查看mongodb官…

我們所熟知的meme梗圖也可以用AI生成了,老外都玩壞了。

meme梗圖不知道大家看到過嘛&#xff1f;相信你們看見下面的圖你就會大叫“臥槽”&#xff0c;原來是這種圖&#xff0c;我以前經常狂刷不止&#xff0c;太有趣了。 其實meme是一個網絡流行語&#xff0c;可譯為模因。在大眾非學術范圍內也可翻譯為我們所熟知的“梗”。其中“表…

SDK環境的安裝(測試使用)

1、安裝 將文件解壓至目錄,我的目錄為:D:\Program Files\Android 解壓后如下: 下載鏈接如下: sdk下載 提取碼見文章最后: 2、配置環境 1、在環境變量中,選擇系統變量,點擊新建。 變量名:ANDROID_HOME 變量值:“你自己的android-sdk安裝路徑” (例如我的:D:\Pro…

CF1955C Inhabitant of the Deep Sea 題解

題目 模擬 首先想到模擬。 但是看到數據范圍&#xff0c;模擬不了。 #include<bits/stdc.h> #include<cstring> #include<queue> #include<set> #include<stack> #include<vector> #include<map> #define int long long #define …

如何在 Linux 中高亮顯示日志關鍵字

在 Linux 系統中&#xff0c;實時查看日志文件通常使用 tailf 命令&#xff0c;但 tailf 本身并不支持高亮顯示關鍵字功能。通過結合 grep、sed 等工具&#xff0c;我們可以實現日志關鍵字高亮。本文將介紹幾種高效的方法來實現這一目標。 方法一&#xff1a;使用 grep --color…

人機交互中有許多不滿足緊致性條件的地方

緊致性條件通常用于描述拓撲空間的性質。一個拓撲空間被稱為緊致的&#xff0c;如果它的任意開覆蓋都有有限子覆蓋。換句話說&#xff0c;對于任何開覆蓋&#xff0c;都可以從中選取有限個開集&#xff0c;它們的并仍然覆蓋整個空間。 滿足緊致性條件的方法通常包括以下幾種&am…

7月8日 四道經典單鏈表oj題

大家好呀&#xff0c;本博客目的在于記錄暑假學習打卡&#xff0c;后續會整理成一個專欄&#xff0c;主要打算在暑假學習完數據結構&#xff0c;因此會發一些相關的數據結構實現的博客和一些刷的題&#xff0c;個人學習使用&#xff0c;也希望大家多多支持&#xff0c;有不足之…

CSS--表格自適應寬度并設置最小寬度

原文網址&#xff1a;CSS--表格自適應寬度并設置最小寬度_IT利刃出鞘的博客、-CSDN博客 簡介 本文介紹怎樣讓HTML的表格自適應寬度。 Java技術星球&#xff1a;way2j.com 問題描述 默認樣式下&#xff0c;表格會出現某一列很窄的情況&#xff1a; 代碼&#xff1a; <h…

Redission 解鎖異常:attempt to unlock lock, not locked by current thread by node id

標題&#xff1a;解鎖異常&#xff1a;Redission中的"attempt to unlock lock, not locked by current thread by node id"問題分析與解決方案 在分布式系統中&#xff0c;鎖是常用的同步機制&#xff0c;用于保護共享資源&#xff0c;避免并發沖突。Redission是一個…

java-多線程 2

### 7. 線程池 線程池是管理和復用線程的機制&#xff0c;可以避免頻繁創建和銷毀線程的開銷。Java 提供了 Executor 框架來管理線程池。 #### 7.1 使用 Executors 工廠類 Executors 工廠類提供了一些靜態方法&#xff0c;用于創建常見類型的線程池。 java import java.uti…

[240708] 中國 AI 企業在世界人工智能大會上展現韌性與創新

目錄 中國 AI 企業在世界人工智能大會上展現韌性與創新 中國 AI 企業在世界人工智能大會上展現韌性與創新 中國科技公司在本周上海舉行的世界人工智能大會上展現出強大的韌性和創新能力。超過150 種 AI 相關產品和解決方案在大會上展出&#xff0c;包括商湯科技、華為、科大訊…

電機工廠MES系統-提升生產效率與質量的關鍵

本文將詳細介紹萬界星空科技電機行業MES系統的特隨著電機行業的快速發展&#xff0c;生產管理的復雜性和精細度日益提高。為了應對這一挑戰&#xff0c;萬界星空科技MES&#xff08;制造執行系統&#xff09;解決方案&#xff0c;為電機行業帶來了前所未有的生產管理變革。點、…

Elasticsearch 分析器(Analyzer)的作用和配置

在Elasticsearch中&#xff0c;分析器&#xff08;Analyzer&#xff09;是文本處理的核心組件&#xff0c;它負責將輸入的文本轉換為可用于搜索和索引的詞項&#xff08;tokens&#xff09;。這一過程涉及多個步驟&#xff0c;包括字符過濾、分詞和標記過濾&#xff0c;共同決定…

js替換對象內部的對象名稱或屬性名稱-(第二篇)遞歸

1.代碼示例&#xff1a; function replaceKey(obj, oldKey, newKey) {// 如果不是對象或者oldKey不存在&#xff0c;直接返回原對象if (typeof obj ! object || !obj || !(oldKey in obj)) return obj;// 如果是數組&#xff0c;遍歷數組每個元素if (Array.isArray(obj)) {obj…

laravel設計模式詳解

目錄 創造模式 一. 工廠方法模式 1. Eloquent ORM 模型工廠 2. 表單請求工廠 3. 服務容器中的工廠方法 二. 抽象工廠模式 1. 配置文件 2. 服務提供者 3. 門面&#xff08;Facades&#xff09; 4. 多環境配置 5. 依賴注入容器 三.原型模式 1. 配置對象的復制 2. 請…

MyBatis的底層機制

手寫MyBatis底層機制 讀取配置文件&#xff0c;得到數據庫連接 思路 引入必要的依賴需要寫一個自己的config.xml文件&#xff0c;在里面配置一些信息&#xff0c;driver&#xff0c;url &#xff0c;password&#xff0c;username需要編寫Configuration類&#xff0c;對 自己…

aosp 單獨grep某種類型文件,加快grep速度。

1、問題 source build/envsetup.sh lunch xxx 后可以 mgrep 可以單獨搜索makefile文件 cgrep 可以單獨搜索c/c文件 jgrep 可以單獨搜索java文件 具體可以查看build/envsetup.sh cat build/envsetup.sh function jgrep() {find . -name .repo -prune -o -name .git -prune -o …

我“硬剛”mmkv開源庫對于版本號的定義贏啦!

我“硬剛”mmkv開源庫勝利啦&#xff01; 前情是這個帖子https://blog.csdn.net/jzlhll123/article/details/139917169 之前項目中將mmkv1.3.4升級到1.3.5或者1.3.6&#xff0c;就從firebase后臺上看到crash。 java.lang.UnsatisfiedLinkError: dlopen failed: library “libmm…

C#面:闡述什么是依賴注入?

依賴注入&#xff08;Dependency Injection&#xff0c;簡稱DI&#xff09;是一種設計模式&#xff0c;用于解耦組件之間的依賴關系。在傳統的編程模式中&#xff0c;一個對象通常會直接創建和管理它所依賴的其他對象。而在依賴注入中&#xff0c;對象不再負責創建和管理它所依…