实际使用捕获时未使用的Lambda捕获警告

时间:2018-09-20 01:44:45

标签: c++ clang

此代码:

void foo(int);
int main() {
    const int i = 0;
    auto l = [i](){foo(i);};
}

godbolt

使用

由clang编译时,将发出编译器错误

-std=c++17 -Werror -Wunused-lambda-capture

错误消息是error: lambda capture 'i' is not required to be captured for this use

错误是正确的:这里可以隐式捕获i,而不必显式捕获。但是,a)警告的名称不正确,因为使用了i,但是警告是针对未使用 lambda捕获的; b)我只是不希望这是一个错误。对于实际未使用的lambda捕获,我想出错,但对于可能被隐式捕获的已使用的显式捕获变量,我不希望出错。

是否有执行此操作的叮当声设置?还是我必须使用编译指示诊断推送/弹出来消除错误?

2 个答案:

答案 0 :(得分:5)

我认为您在这里很不幸。如果我们检查实现此功能[Sema] Add warning for unused lambda captures的评论,就会发现有关如何使警告静音的讨论已得到广泛讨论。包括沉默未使用警告的规范clang方法,该方法强制转换为无效:

  

我认为不应在此处使用预期警告,因为您在lambda中具有(void)fname(如果在本地进行测试,则不会收到此警告)。

see it live确实可以使用,但是在这种情况下感觉很傻。

使用-Wno-unused-lambda-capture,但这对您来说不是一个好选择:

  

我认为,如果将“ -Wno-unused-lambda-capture”添加到CXX /目录中此修补程序修改的所有测试的选项中,则该修补程序会更整洁。这样可以避免多余的(void)使用,并确保(void)使用不会干扰可能仅在捕获列表中使用的原始意图。

从捕获中删除变量,因为它没有被过分使用,但正如指出的那样,由于MSVC不执行此优化,因此暴露了实现上的分歧:

  

如果我从列表中删除kDelta,它将在没有任何警告的情况下进行编译   捕获数量:

#include <stdio.h>

int main(void) {
  const int kDelta = 10000001;
  auto g = [](int i)
           {
             printf("%d\n", i % kDelta);
           };
  g(2);
}
     

但是随后Microsoft C ++编译器将引发错误:

error C3493: 'kDelta' cannot be implicitly captured because no default capture mode has been specified

我们可以看到这种情况live as well,并且确实从捕获中删除了i确实可以解决clang和gcc,但不能解决MSVC。

适用于所有限制的另一种解决方案是显式捕获[i=i],但听起来这也不是理想的解决方案(see it live)。

如果我们可以在此处应用[[maybe_unused]],但不能在此应用,那就太好了。

答案 1 :(得分:0)

我没有一个好的解决方案,但是我们已经实施了一个解决方案。

void foo(int);
int main() {
    const int i = 0;
    auto l = [LAMBDA_CONSTANTS(&i)](){foo(i);};
}

LAMBDA_CONSTANTS是LambdaConstants.h中定义的宏,我们在需要时将其包括在内。

其内容是:

#ifndef LAMBDA_CONSTANTS_H
#define LAMBDA_CONSTANTS_H

/*
    given a lambda that wants to capture two constants

    const auto k1 = 1000;
    const auto k2 = 2000;
    int v = 0;

    auto lambda = [&v, &k1, &k2]() {
        v = k1 * k2;
    }

    Then unfortunately clang will correctly warn about unnecessary captures. And MSVC will fail to compile if you don't capture.

    https://stackoverflow.com/questions/52416362/unused-lambda-capture-warning-when-capture-is-actually-used

    An imperfect solution is to declare the lambda using the LAMBDA_CONSTANTS macro.

    auto lambda = [&v
    LAMBDA_CONSTANTS(&k1, &k2)
    ](){
        v = k1 * k2;
    }

    This should work correctly. Most of the time.

NOTE: There is no comma after the final capture variable before the LAMBDA_CONSTANTS macro. The macro is variadic and will work with 1 or more captures.
*/
#ifndef LAMBDA_CONSTANTS
#if _MSC_VER
#define LAMBDA_CONSTANTS(...) ,__VA_ARGS__
#else 
#define LAMBDA_CONSTANTS(...)
#endif
#endif


#endif // LAMBDA_CONSTANTS_H
相关问题