Scott Meyers 的Effective C++建议赋值运算符应返回对*this
. GCC-Weffc++
似乎概括了这一原则,建议就地算术运算符(例如 prefix ++
)的重载也应该返回对类类型实例的引用。
但是对于CRTP,GCC 显然无法识别然后返回正确的引用类型:
template <typename DERIVED>
class Foo
{
public:
DERIVED& operator++(void)
{
++data;
return static_cast<DERIVED&>(*this);
}
private:
int data;
};
class Bar : public Foo<Bar>
{ /* ... */ };
这里,DERIVED&
是真正应该返回的类型,因为它Bar
不是. 但 GCC 给出以下警告:Foo<Bar>
Bar
operator_return_this.cpp:5:33: warning: prefix ‘DERIVED& Foo<DERIVED>::operator++()’ should return ‘Foo<DERIVED>&’ [-Weffc++]
DERIVED& operator++(void)
^
operator_return_this.cpp: In instantiation of ‘class Foo<Bar>’:
operator_return_this.cpp:15:24: required from here
operator_return_this.cpp:5:18: warning: prefix ‘DERIVED& Foo<DERIVED>::operator++() [with DERIVED = Bar]’ should return ‘Foo<Bar>&’ [-Weffc++]
DERIVED& operator++(void)
第一个警告有点明智——编译器无法判断该类旨在用于 CRTP,因此它没有意识到该类DERIVED
将继承自Foo<DERIVED>
. (编辑:实际上,通过使用 astatic_cast
而不是 C 风格的转换,您确实可以确保它DERIVED
确实是派生类型,因此如果编译器推迟发出此警告,直到查看函数的实现,它甚至可以抑制误报没有看到Bar
.) 的定义。但是第二个警告,它看到了实际的 CRTP 声明,对我来说根本没有意义,因为它应该能够告诉它Bar&
算作Foo<Bar>&
.
但是,当使用带有运算符重载的 CRTP 时,即使是第一个警告也是虚假的。这是否意味着-Weffc++
根本不能与 CRTP 一起使用(假设您想避免虚假警告)?