我注意到我的生产 C++17 代码中关于泛型 lambda 的行为不一致。我终于能够将其分解为以下最小示例。
为 x86_64 gcc 9.3 提供注释,但不为 x86_64 gcc 10.1 提供注释
#include <string>
#include <iostream>
struct STR { int a; };
int main()
{
auto lambda =
[]( const auto& executionContext )
{
if ( !executionContext.empty() )
return;
[[maybe_unused]]STR objSTR;
};
lambda( std::string{} );
return 0;
}
编译器消息如下:
<source>: In instantiation of 'main()::<lambda(const auto:1&)> [with auto:1 = std::__cxx11::basic_string<char>]':
<source>:17:27: required from here
<source>:3:8: note: 'struct STR' has no user-provided default constructor
3 | struct STR { int a; };
| ^~~
<source>:3:18: note: and the implicitly-defined constructor does not initialize 'int STR::a'
3 | struct STR { int a; };
| ^
Compiler returned: 0
我知道我的结构不会初始化 'int STR::a' 但如果我现在用
auto
替换 std::string
,注释就会完全消失。
给出 x86_64 gcc 9.3 和 x86_64 gcc 10.1 的注释
#include <string>
#include <iostream>
struct STR { int a; };
int main()
{
auto lambda =
[]( const std::string& executionContext )
{
if ( !executionContext.empty() )
return;
[[maybe_unused]]STR objSTR;
};
lambda( std::string{} );
return 0;
}
我还可以删除通用 lambda 的注释,如下所示:
给出 x86_64 gcc 9.3 和 x86_64 gcc 10.1 的注释
#include <string>
#include <iostream>
struct STR { int a; };
int main()
{
auto lambda =
[]( const auto& executionContext )
{
if ( !executionContext.empty() )
return;
[[maybe_unused]]STR objSTR{};
};
lambda( std::string{} );
return 0;
}
如果它有任何模板特定的原因,我可以接受,但从 GCC 10.1 开始,第一个示例中没有通用 lambda 的注释! GCC 9.3 在这里行为不正确吗?
在线演示:https://godbolt.org/z/4M8MP7WGn
标志: -Wall -Wextra -O3 -std=c++17
编译器:x86_64 gcc 9.3/x86_64 gcc 10.1
GCC 9.3 中关于 struct STR 中未初始化成员的注释在技术上是正确的,因为默认构造函数不会初始化 int a。
GCC 10.1 可能放宽了此检查或改进了通用 lambda 的上下文感知。使用 {} 初始化 objSTR 是确保初始化成员的好习惯。 如果该注释很烦人但无害,您可以安全地忽略它或显式初始化该结构。不同的编译器版本通常在警告和注释行为方面存在差异,这可以解释观察到的不一致情况。