首页 > 解决方案 > gcc >=10.1 和 clang 不检测未使用但设置 lambda

问题描述

考虑以下程序:

template <unsigned int I>
int f(int x)
{
    auto task = [&]() { ++x; };
    if constexpr (I == 0) {
        task();
    }
    return x;
}

int main()
{
    f<1>(3);
}

在 gcc 9.3 上编译时-std=c++17 -Wall -pedantic会发出警告

warning: variable 'task' set but not used [-Wunused-but-set-variable]
    4 |     auto task = [&]() { ++x; };

但是对于较新的 gcc 版本,不会出现这样的警告。请注意,根据手册-Wunused-but-set-variable由 启用-Wall

同样使用clang,不会出现这样的警告。

在godbolt上测试它。

这是编译器的缺点,还是需要/预期这种行为(缺乏警告)?

标签: c++gccclangwarnings

解决方案


考虑这个稍微修改过的代码:

template <unsigned int I>
int f(int x)
{
    auto task = [&]() { ++x; };
    if constexpr (I == 0) {
        task();
    }
    return x;
}

int main()
{
    f<0>(3);
    f<1>(3);
}

使用gcc 9.3-std=c++2a -Wall -Werror你会得到一个错误(警告被视为错误)

<source>: In instantiation of 'int f(int) [with unsigned int I = 1]':
<source>:14:11:   required from here
<source>:4:10: error: variable 'task' set but not used [-Werror=unused-but-set-variable]
    4 |     auto task = [&]() { ++x; };
      |          ^~~~
cc1plus: all warnings being treated as errors

这很糟糕,因为代码完全没问题,它可以被认为是触发警告的错误。显然这已在 gcc >= 10.1 中修复。

有人可能会争辩说可以/应该将声明task移到if constexpr分支中,但随后认为这也使 gcc 发出警告:

template <unsigned int I>
int f(int x)
{
    auto task = [&]() { ++x; };
    if constexpr (I == 0) {
        task();
    } else if constexpr (I == 1) {
        task();
    } 
    return x;
}

int main()
{
    f<0>(3);
    f<1>(3);
    f<2>(3);
}

推荐阅读