簡體   English   中英

嵌套的 lambda 捕獲變量給出不正確的警告

[英]Nested lambda capture of variable gives incorrect warning

我正在使用嵌套的 lambda 來瀏覽一些數據。
外層lambda做一些處理,然后調用內層lambda。

我收到以下警告:

x86-64 clang 13.0.1 - 2629ms (104630B) ~1800 lines filtered

    Output of x86-64 clang 13.0.1 (Compiler #1)

<source>:9:34: warning: class '' does not declare any constructor to initialize its non-modifiable members
    const auto PickVarAtRandom = [&]<bool SATvar> {
                                 ^
<source>:9:34: note: in instantiation of member class '' requested here
<source>:18:41: note: in instantiation of function template specialization 'main()::(anonymous class)::operator()<true>' requested here
    const auto result = doPick.template operator()<true>();
                                        ^
<source>:10:13: note: reference member '' will never be initialized
        if (Length > 50) { printf("hallo"); return false; }

該代碼使用嵌套的 lambda 調用。 以下代碼將在Godbolt中重現該問題。

#include <stdlib.h>
#include <stdio.h>


int main() {
    const auto Length = rand() % 2;

    //warning: class '' does not declare a constructor ...
    //                           V
    const auto PickVarAtRandom = [&]<bool SATvar> {
        if (Length > 0) { printf("one  %i", Length); return false; }
        else            { printf("zero %i", Length); }
        return true;
    };

    const auto doPick = [&]<bool SATvar>() {
        return PickVarAtRandom.template operator()<SATvar>();
    };

    const auto result = doPick.template operator()<true>();
}

如果只使用一個 lambda,錯誤就會消失:

//no warning
#include <stdlib.h>
#include <stdio.h>

int main() {
    const auto Length = rand() % 100;

    const auto PickVarAtRandom = [&]<bool SATvar> {
        if (Length > 50) { printf("hallo"); return false; }
        return true;
    };

 
    const auto result = PickVarAtRandom.template operator()<true>();
}

我在 MacOS 上使用 clang 14,但為了在 Godbolt 中重現警告,我需要 select clang 13。

clang++ --version
Apple clang version 14.0.0 (clang-1400.0.29.102)
Target: arm64-apple-darwin21.6.0
Thread model: posix

為什么使用嵌套 lambda 會收到此警告?
我可以抑制警告嗎?
或者有沒有辦法在仍然使用嵌套 lambdas 的同時擺脫警告?

這可能是來自 clang 的錯誤,因為 gcc 和 clang 的更新版本 (>13) 都沒有使用-std=c++20給出此警告。

我可以抑制警告嗎?

是的。

參見神螺栓

這是在此提交中修復的編譯器錯誤: https://github.com/llvm/llvm-project/commit/f7007c570a216c0fa87b863733a1011bdb2ff9ca

如您所見,提交位於 clang 14 中,特別是在標簽llvmorg-14.0.0-rc2llvmorg-14.0.0-rc3 因此,警告不會出現在帶有 clang 14 的 Godbolt 上,但出現在 clang 13 上是有道理的,我猜你機器上的版本不是最新的 clang14。

不幸的是,這個警告似乎沒有附加任何標志。 如果您無法升級,我認為在代碼中抑制它的唯一方法是使用-Weverything的編譯指示:

#include <stdlib.h>
#include <stdio.h>

int main() {
    const auto Length = rand() % 2;

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weverything"
    const auto PickVarAtRandom = [&]<bool SATvar> {
#pragma GCC diagnostic pop
        if (Length > 0) { printf("one  %i", Length); return false; }
        else            { printf("zero %i", Length); }
        return true;
    };

    const auto doPick = [&]<bool SATvar>() {
        return PickVarAtRandom.template operator()<SATvar>();
    };

    const auto result = doPick.template operator()<true>();
}

神螺栓

您當然可以使用-Wno-everything-w進行編譯,但這通常是個壞主意。

至於為什么你會收到這個警告......我從查看提交的猜測是附加條件cast<CXXRecordDecl>(D)->getTemplateDepth() > TemplateArgs.getNumRetainedOuterLevels()使得 clang 的某些部分正確地將PickVarAtRandom視為本地,它以某種方式解決了警告。 也許您可以在這里找到更多信息。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM