兩個 int 變數,一個是參考,當被 lambda 捕獲時,在 MSVC 的 c 20 中的型別不同。為什么?
Scott 在編譯時確定型別的技術對 c 14 和 17 產生了預期的結果,但對 c 20 卻沒有。但是,似乎這種奇怪的差異也出現在早期版本的其他編譯中。
具體來說,兩個整數,一個是參考,當被值或參考捕獲時會產生不同的型別。int和int &。然而,早期版本會產生預期的型別。當按值捕獲時,兩者都是鍵入的int。當通過參考捕獲時,兩者都是int &.
// Scott Meyer's compile time Type Deduction technique
template<typename T>
class TD;
int main()
{
int i{ 1 };
int& ri = i;
[i, ri]() mutable {
TD<decltype(i)> WhatAmI1; // c 14, c 17 TD<int>, c 20 TD<int>
TD<decltype(ri)> WhatAmI2; // c 14, c 17 TD<int>, c 20 TD<int &>
}();
[&i, &ri]() mutable {
TD<decltype(i)> WhatAmI3; // c 14, c 17 TD<int&>, c 20 TD<int>
TD<decltype(ri)> WhatAmI4; // c 14, c 17 TD<int&>, c 20 TD<int &>
}();
}
進一步探索這一點,生成的代碼符合預期,并且對于捕獲的值和捕獲的參考都是相同的。
int main()
{
int i{ 1 };
int& ri = i;
[i, ri]() mutable {
i = 2;
ri = 3;
}();
[&i, &ri]() {
i = 2;
ri = 3;
}();
}
[i, ri]() mutable {
i = 2;
00007FF7F506187F 48 8B 85 E0 00 00 00 mov rax,qword ptr [this]
00007FF7F5061886 8B 00 mov eax,dword ptr [rax]
00007FF7F5061888 83 C0 02 add eax,2
00007FF7F506188B 48 8B 8D E0 00 00 00 mov rcx,qword ptr [this]
00007FF7F5061892 89 01 mov dword ptr [rcx],eax
ri = 3;
00007FF7F5061894 48 8B 85 E0 00 00 00 mov rax,qword ptr [this]
00007FF7F506189B 8B 40 04 mov eax,dword ptr [rax 4]
00007FF7F506189E 83 C0 03 add eax,3
00007FF7F50618A1 48 8B 8D E0 00 00 00 mov rcx,qword ptr [this]
00007FF7F50618A8 89 41 04 mov dword ptr [rcx 4],eax
[&i, &ri]() {
i = 2;
00007FF7F506190F 48 8B 85 E0 00 00 00 mov rax,qword ptr [this]
00007FF7F5061916 48 8B 00 mov rax,qword ptr [rax]
00007FF7F5061919 8B 00 mov eax,dword ptr [rax]
00007FF7F506191B 83 C0 02 add eax,2
00007FF7F506191E 48 8B 8D E0 00 00 00 mov rcx,qword ptr [this]
00007FF7F5061925 48 8B 09 mov rcx,qword ptr [rcx]
00007FF7F5061928 89 01 mov dword ptr [rcx],eax
ri = 3;
00007FF7F506192A 48 8B 85 E0 00 00 00 mov rax,qword ptr [this]
00007FF7F5061931 48 8B 40 08 mov rax,qword ptr [rax 8]
00007FF7F5061935 8B 00 mov eax,dword ptr [rax]
00007FF7F5061937 83 C0 03 add eax,3
00007FF7F506193A 48 8B 8D E0 00 00 00 mov rcx,qword ptr [this]
00007FF7F5061941 48 8B 49 08 mov rcx,qword ptr [rcx 8]
00007FF7F5061945 89 01 mov dword ptr [rcx],eax
}();
鏈接到編譯器資源管理器https://godbolt.org/z/oe9KPcWWv
uj5u.com熱心網友回復:
C 20 模式下 Clang、GCC 和 MSVC 的行為對于支持 lambda 的所有標準版本都是正確的。decltype(i)并decltype(ri)產生命名變數的型別。它不會被重寫來參考閉包物件的成員,就像decltype((ri)). (參見C 17 草案 N4659 中的[expr.prim.lambda.capture]/14專門處理此問題)
顯然,MSVC 在 C 20 之前對標準模式的默認行為與 lambda 的處理方式不一致。根據檔案/Zc:lambda,必須給出標志以處理符合標準的 lambda。使用此選項,MSVC 會為 C 17 和 C 14 模式生成與 C 20 模式相同的結果。
例如,請參閱此錯誤報告,該報告已作為非錯誤關閉,并帶有使用此標志的說明。另請注意,它似乎不包含在/permissive-.
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/443094.html
上一篇:如何檢查無效地址/已洗掉指標?
