Scott Meyers' Effective C ++ 建议赋值运算符应返回对*this
的引用。 GCC的-Weffc++
似乎概括了这个原则,以建议就地算术运算符的重载(例如前缀++
)也应该返回对类类型实例的引用。
但对于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
而不是Foo<Bar>
是&#34;真实&#34; Bar
实例的类型。但GCC发出以下警告:
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
将继承自{{1} }}。 (编辑:实际上,通过使用Foo<DERIVED>
代替C风格的广告,你做确保static_cast
确实是派生类型,因此,如果编译器推迟发出此警告,直到查看该函数的实现,即使没有看到DERIVED
的定义,它也可以抑制误报。)但是第二个警告,它在哪里看到实际的CRTP声明,对我来说根本没有意义,因为它应能够告诉我Bar
计为Bar&
。
但是当使用CRTP和运算符重载时,即使是第一个警告也是假的。这是否意味着Foo<Bar>&
无法与CRTP一起使用(假设您想避免虚假警告)?