据我所知,这应该是合法的(并且不会被编译器忽略)。
更正:
-
应该合法:是的,它可以应用于非静态数据成员的声明,
- 不应被忽略:不,由实现决定是否以及如何使用此属性。
虽然[dcl.attr.unused]/2 指定maybe_unused 属性可以应用于非静态数据成员的声明[强调我的]:
属性可以应用于声明类、typedef-name、变量(包括结构化绑定声明)、非静态数据成员 、函数、枚举或枚举数。
对于如何应用这个属性的实现没有严格的要求,只有一个建议关于实现应该如何应用它,如每[dcl.attr.unused]/4 [强调我的]:
推荐做法:对于标记为maybe_unused 的实体,实现不应发出该实体或其结构化绑定(如果有)已使用或未使用的警告。对于未标记为 maybe_unused 的结构化绑定声明,除非其所有结构化绑定都未使用,否则实现不应发出此类警告。
这意味着只要实现允许应用于非静态数据成员的声明,它们就符合标准,并且属性未实现不是编译器错误使用推荐的做法,即使我们可以争辩说编译器应该能够诊断一个类的未使用的非静态数据成员,该类定义为在单个翻译单元中使用内部链接。例如。在以下示例中:
// test.cpp
namespace {
struct Foo {
int member{1};
void bar() {
[[maybe_unused]] int local = 0;
}
};
void bar() {
Foo f{};
f.bar();
}
} // namespace
Foo的非静态数据成员member没有被使用;这是可诊断的,maybe_unused 属性可以说是用来抑制这种实现定义的未使用警告。但是,GCC 和 Clang 都没有针对上述情况发出警告,并且对于 GCC 和 Clang 都没有与“本地类的未使用的 public 字段或隐藏的类的内部链接”相关的警告。
那么我们可以像我们自己一样为什么 Clang not 发出一个实现定义的警告,即对于非静态数据成员的情况,该属性将被忽略?原因是 Clang 确实为未使用的 private 静态数据成员发出了 -Wunused-private-field warning:
struct Foo {
void bar() {
int local = 0;
}
private:
int member{1};
// Clang: warning: private field 'member' is not used
};
而 GCC 没有,这也包括为什么 GCC(正确地)警告 maybe_unused 属性将被它对于非静态数据成员(甚至是私有数据成员)忽略,因为它根本不会诊断未使用的私有数据成员(而 Clang 有)。这些行为都是正确的,因为它位于实现定义的行为领域。
我们可能会注意到 2016 年的 GCC 错误报告要求 Clang 实现的功能:
曾经
...确认为增强功能。
在重复标记的错误报告Bug 87409 - Implement -Wunused-private-field 中,Jonathan Wakely 表示如果此功能要在 GCC 中实现,他们还需要实现对它的抑制(也许) 未使用的属性:
如果成员声明具有未使用的属性,Clang 会抑制警告,我们也需要这样做。
处理实现定义行为中的实现差异
由于这里没有编译器错误需要解决,Foo 类的“可移植”(对于选择的特定编译器)实现(如果它有,比如说,(可能)未使用的私有数据成员),wrt未使用的警告,例如是使用特定于实现的编译指示,如所示,例如在@0x5453: self-answer 中,尝试对齐所选编译器的实现定义行为。
另一种方法是考虑在全局范围内完全删除 Clang 的 -Wunused-private-field 警告 (-Wno-unused-private-field),而将此类诊断留给静态分析工具。