GCC 忽略重写成员函数的 nodiscard 属性是否正确?
Is GCC correct to ignore the nodiscard attribute on overridden member functions?
由于 问题和答案,属性是否被继承不是 100% 清楚的,但可能不是,因为它没有在标准中说明。这就是为什么如果我们在基 class 中只有标记为 nodiscard
的声明,并使用 Clang 进行编译,我们只会在使用“基”指针访问对象时收到警告。
以下代码的问题是在使用 GCC(版本 8.1 到 11.1)编译时根本不会发出警告。 nodiscard
仅在 Child1
、两个 class 中或仅在 Base
中,通过 Base
指针或 Child1
指针调用,这些都无济于事。
#include <memory>
class Base {
public:
[[nodiscard]]
virtual int getIdentifier() const = 0;
};
class Child1 : public Base {
public:
[[nodiscard]]
int getIdentifier() const override {
return 1;
}
};
int main()
{
std::unique_ptr<const Child1> p1 { new Child1 };
p1->getIdentifier();
std::unique_ptr<const Base> p2 { new Child1 };
p2->getIdentifier();
}
这是 GCC 中的一种错误(不太可能,因为编译器资源管理器中可用的每个版本,从 8.1 到 11.1,都会产生相同的结果),还是我做错了什么?
对我来说这似乎是一个错误,因为它适用于 Clang。但是这个bug需要2个条件才能触发:
virtual
方法
- 间接寻址。在您的情况下,
unique_ptr
可以做到。如果你得到一个简单的实例并直接调用函数,你会看到警告。
但如果您需要解决方法,可以使用其他属性。这是一个小样本:
struct A{
[[gnu::warn_unused_result]]
virtual int foo() {
return 1;
}
};
int main(){
A a;
a.foo();
}
此属性适用于 GCC 和 Clang。
另一个建议:您可以使用像[[nodiscard, gnu::warn_unused_result]]
这样的属性,这将适用于所有编译器。
由于 nodiscard
的声明,并使用 Clang 进行编译,我们只会在使用“基”指针访问对象时收到警告。
以下代码的问题是在使用 GCC(版本 8.1 到 11.1)编译时根本不会发出警告。 nodiscard
仅在 Child1
、两个 class 中或仅在 Base
中,通过 Base
指针或 Child1
指针调用,这些都无济于事。
#include <memory>
class Base {
public:
[[nodiscard]]
virtual int getIdentifier() const = 0;
};
class Child1 : public Base {
public:
[[nodiscard]]
int getIdentifier() const override {
return 1;
}
};
int main()
{
std::unique_ptr<const Child1> p1 { new Child1 };
p1->getIdentifier();
std::unique_ptr<const Base> p2 { new Child1 };
p2->getIdentifier();
}
这是 GCC 中的一种错误(不太可能,因为编译器资源管理器中可用的每个版本,从 8.1 到 11.1,都会产生相同的结果),还是我做错了什么?
对我来说这似乎是一个错误,因为它适用于 Clang。但是这个bug需要2个条件才能触发:
virtual
方法- 间接寻址。在您的情况下,
unique_ptr
可以做到。如果你得到一个简单的实例并直接调用函数,你会看到警告。
但如果您需要解决方法,可以使用其他属性。这是一个小样本:
struct A{
[[gnu::warn_unused_result]]
virtual int foo() {
return 1;
}
};
int main(){
A a;
a.foo();
}
此属性适用于 GCC 和 Clang。
另一个建议:您可以使用像[[nodiscard, gnu::warn_unused_result]]
这样的属性,这将适用于所有编译器。