-Wshadow is not that bad. We live in a modern world and don't use C if we can use C++ with a better defined scope and namespaces. So we can catch more errors on compile time.
First: what kind or errors can be detected with -Werror=shadow
Warn whenever a local variable or type declaration shadows another variable, parameter, type, class member, or whenever a built-in function is shadowed.
struct A { int i; // note: shadowed declaration is here void func(int i) {} // error: declaration of 'i' shadows a member of 'A' [-Werror=shadow] };
This kind or error also occurs if you define a constructor like following code. It defines a type Axis which has a title and a range. The range must be valid. The constructor of the Axis does something. So aggregate initialization is not possible.
struct Axis { string title; Range range; Axis(string title, Range range) : title(title), range(range) // error: declaration of 'range' shadows a member of 'Axis' // error: declaration of 'title' shadows a member of 'Axis' { // check if range is valid, error otherwise } };
You can, of course, rename the constructor arguments or member variables. But that is not nice and results in either ugly code or a less proper interface.
The right solution is to split your type into two. One which only store data and another which does something with that data. Let's call the data-type AxisData. Try again:
struct Axis { struct AxisData { string title; Range range; }; AxisData d; Axis(string title, Range range) : d{title, range} { // check if range.isValid() } };
No more errors! The extra variable d is no overhead, as you can see in my previous post.
To hide this implementation details from the programmer, provide some access function and switch from struct to class because Axis is now a type which manage it's data.
So this is the (final, add some references) implementation:
class Axis { struct AxisData { string title; Range range; }; AxisData d; public: Axis(string title, Range range) : d{title, range} { // check if range.isValid() } string title() const { return d.title; } Range range() const { return d.range; } };