-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;
}
};