3

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 一起使用(假设您想避免虚假警告)?

4

0 回答 0