c++cppcheckone-definition-rule

cppcheck: one definition rule is violated when overriding


In the following code (which is a minimal example based on a much more complex code), a base class defines a struct local to the class. A derived class overrides this definition, but uses also the definition in the base class.

#include <iostream>

struct base {
  struct update;

  void apply(int& x);
};

struct base::update {
  void operator()(int& x)
  {
    ++x;
  }
};

void base::apply(int& x) { update{}(x); }

struct deriv : public base {
  struct update;

  void apply(int& x, int& y);
};

struct deriv::update {
  void operator()(int& x, int& y)
  {
    typename base::update{}.operator()(x);
    ++y;
  }
};

void deriv::apply(int& x, int& y) { update{}(x, y); }

int main()
{
  base b;

  int x = 1;

  b.apply(x);
  std::cout << x << std::endl;

  int y = 2;
  deriv d;
  d.apply(x, y);

  std::cout << x << ' ' << y << std::endl;
  
  return 0;
}

Compiling with gcc and -Wall -Wextra does not issue any warning. The output of the code is as expected

2
3 3

However, when analyzing the code with cppcheck, with --enable=all, I get the following:

Checking test.cpp ...
test.cpp:25:24: style: Parameter 'x' can be declared with const [constParameter]
  void operator()(int& x, int& y)
                       ^
test.cpp:9:1: error: The one definition rule is violated, different classes/structs have the same name 'update' [ctuOneDefinitionRuleViolation]
struct base::update {
^
test.cpp:24:1: note: The one definition rule is violated, different classes/structs have the same name 'update'
struct deriv::update {
^
test.cpp:9:1: note: The one definition rule is violated, different classes/structs have the same name 'update'
struct base::update {

The first reported error (Parameter 'x' can be declared with const) seems clearly a false positive, as clearly I need non-const reference to be able to modify it, and in fact the code obviously does not compile with a const int&.

But what about the second error on ODR violation? Is this a correct diagnose, and if so why cannot I override the definition of update?


Solution

  • It is also a false positive. There is nothing wrong with declaring a nested class of the same name in the derived class. The two nested classes will be separate entities and each can have one definition per one-definition-rule.