Cppcoreguidelines: Con.1's exception is confusing

Created on 3 Jul 2017  路  14Comments  路  Source: isocpp/CppCoreGuidelines

It states:

Function arguments are rarely mutated, but also rarely declared const. To avoid confusion and lots of false positives, don鈥檛 enforce this rule for function arguments.

But then Con.3 is another rule that talks about const in function parameters "by default". If a reader reads only Con.1 and not Con.3, they might take away the wrong message w.r.t. pointer to const. Maybe make the "don't enforce this rule" verbiage more in line with the rest about redundant const.

Most helpful comment

But the types of the parameters are also present in declarations of the function and don't have to match, that's what causes confusion, and has no analogy for normal local variables.

int f(int);
int f(const int i) { return i + 1; }

This does confuse people, and has nothing to do with whether the const is on the left or the right. If people choose not to add the const to the function definition, to avoid confusing other readers of their code, that's a reasonable choice, and that's why the guideline says not to flag those cases.

All 14 comments

If I understand this correctly, the exception doesn't advise against making function arguments const but advises tools against flagging non-const, by-value function parameters. So it probably should be put into the enforcement part.

It seems to me that the exception sounds a bit like wishful thinking. It says "Function arguments are rarely mutated" but doesn't it really mean that they are rarely intended to be mutated? The general intention is not to change them. But without declaring them const nothing prevents the intentions being accidentally subverted. And isn't that what the guidelines are for? To protect us from accidentally doing that which we did not intend to do?

Rather than calling them "false positives" couldn't you have different levels of paranoia on the tools so that people can choose how strict they want their code to conform? That way you let them know they could be even safer by changing their practices without forcing them into it.

I think the real reason for this exception is the fact that const in function arguments is strongly associated with passing by pointer or reference, and signatures like void f(char* const ptr) can cause a lot of confusion.

Perhaps is would be better to state it explicitly in the rule instead of saying only "_function arguments are rarely declared const_".

void f(char* const ptr) declares a function of type void(char*) and I've seen people confused when they thought they could add a "non-const" void f(char* ptr) overload.

I seem to remember there was a proposal (that was rejected) to recommend always placing the const to the right of the type because that is more logical. I think that would make it more teachable (when learned from scratch). It would be less confusing for beginners because there is one simple rule:

Read the type from right to left:

int x; // x is a (mutable) int

int const x; // x is a (const) int

int const * x; // x is a (mutable) pointer to a (const) int

int * const x; // x is a (const) pointer to a (mutable) int

int const * const x; // x is a (const) pointer to a (const) int

I feel that, when taught from scratch, this way of expressing the type is the most comprehensible. I think that confusion comes when people are taught the traditional way of expressing const so they have trouble extrapolating that to more complex scenarios.

const int x;

const int * x; // beginners often confuse which is const

const int * const x; // super confused now

int * const x; // wait... is this even a 'thing'?

There is no simple rule to be drawn from the traditional ordering and it regularly causes confusion when beginners encounter more complex types.

It's probably a little extreme but I would favor suggesting the first example as canonical ordering so that tools could be configured to warn when declarations use the more traditional form.

@galik however much you wish for it, nobody is going to change billions of lines of existing C++ code to be written in that style. Trying to enforce it as the canonical style is doomed to fail, and IMHO is off-topic for the guidelines.

@galik

It says "Function arguments are rarely mutated" but doesn't it really mean that they are rarely intended to be mutated?

No, I think it means what it says. They are rarely mutated in practice, so if tools warned about them there would be lots of noise and confusion. What's wishful thinking is that everybody will start putting the const on the right and all users will understand the rules about top-level const on function parameter types.

I don't really see a problem here, but maybe the text can be changed to explain that since many users don't understand the meaning of top-level const on a function parameters, declaring them const-by-default is not recommended. There could also be a note to point out that this doesn't conflict with Con.3 because they're talking about completely different things.

@jwakely The guidelines do make style recommendations so, I don't think it is necessarily off topic. But I also wasn't expecting it to be taken up. The real point (the reason I posted it) was that @cubbimew showed a potential error when confusing how types are declared. I think that problem is rather deeper and should not necessarily inhibit recommending safer practices (const parameters).

@jwakely They are rarely mutated in practice..

Given that, in a function body, parameters have the same visibility/scope as local variables (they are essentially no different) I suspect your statement could be made of all local variables. Mostly people do not mutate variables they do not intend. Yet the guidelines still recommend making them const.

It just feels a little inconsistent to me.

Please take the argument elsewhere. My issue is only about that specific verbiage, not about const in general.

But the types of the parameters are also present in declarations of the function and don't have to match, that's what causes confusion, and has no analogy for normal local variables.

int f(int);
int f(const int i) { return i + 1; }

This does confuse people, and has nothing to do with whether the const is on the left or the right. If people choose not to add the const to the function definition, to avoid confusing other readers of their code, that's a reasonable choice, and that's why the guideline says not to flag those cases.

@remyabel do you have a specific recommendation for better wording? I'm not sure I understand your precise concern, if people only read the very first guideline and don't make it to the third one (in a list of hundreds) we can't really help them.

@remyabel Please take the argument elsewhere. My issue is only about that specific verbiage, not about const in general.

I really didn't think the conversation was off topic tbh but I apologize for subverting your issue.

Per our discussion, right-to-left may be more logical but as has been pointed out above, there are billions of lines of code out there. It would be difficult to move this code and would likely confuse people who are used to the existing patterns. Thank you for the great discussion, however!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

galik picture galik  路  3Comments

HowardHinnant picture HowardHinnant  路  3Comments

imre-palik picture imre-palik  路  6Comments

franzhollerer picture franzhollerer  路  5Comments

JVApen picture JVApen  路  4Comments