I'm OK with adding this to the style guide, although we may want to add rationale when we do so, as it's not immediately obvious to everyone why this can be a bad pattern.PK
--
Chromium Developers mailing list: chromi...@chromium.org
View archives, change email options, or unsubscribe:
http://groups.google.com/a/chromium.org/group/chromium-dev
--
If possible, this should also be made part of our clang style checker. Automatic tools always are better at finding those issues. :)You can just file a bug for now, so we remember this (and post the link here ideally). Thanks!
I received a concern about making this strict rule because there are some cases that returned pointer is not considereda part of the state of the object, so I'll make it just a strong recommendation (like const accessor in google style guide) withclear explanation.
On Wed, Jun 6, 2012 at 1:27 PM, oshima <osh...@chromium.org> wrote:I received a concern about making this strict rule because there are some cases that returned pointer is not considereda part of the state of the object, so I'll make it just a strong recommendation (like const accessor in google style guide) withclear explanation.This confusion is actually part of why we have this rule. The problem is that in general, _all_ returned pointers are "part of the state" because the issue is not whether they're members of the const object, but whether there is anything in the transitive closure of everything accessible from the returned pointer that allows you to affect something that the const object sees. The answer to this question is practically always "yes" (indeed, if not, why would you even have an accessor for this pointer?) and thus this non-const returned pointer can basically always be used to violate logical constness.To put this another way, consider oshima's example code, but imagine that the implementation of HTMLElement does not in fact include a parent HTMLElement*, but simply has some pointer to the top-level document. parent() is then implemented by walking the tree to find the parent. In this case, the returned parent pointer is not part of the child's state, so one might assume that the access pattern Gregg describes is OK. But the usage in oshima's example shows that logical constness is still violated once the pointer is returned. Generalize this, and you will understand why after some discussion we eventually concluded that returning a non-const pointer from a const accessor is basically never OK.
(FWIW, WebKit's existing code violates logical constness a lot; I started a thread about this once, and got an OK to at least make these sorts of accessors non-const, which I checked in a patch or two for, but there are still many problems and fixing them all would take a lot of time and effort.)
PK--
On Wed, Jun 6, 2012 at 2:36 PM, Peter Kasting <pkas...@chromium.org> wrote:On Wed, Jun 6, 2012 at 1:27 PM, oshima <osh...@chromium.org> wrote:I received a concern about making this strict rule because there are some cases that returned pointer is not considereda part of the state of the object, so I'll make it just a strong recommendation (like const accessor in google style guide) withclear explanation.This confusion is actually part of why we have this rule. The problem is that in general, _all_ returned pointers are "part of the state" because the issue is not whether they're members of the const object, but whether there is anything in the transitive closure of everything accessible from the returned pointer that allows you to affect something that the const object sees. The answer to this question is practically always "yes" (indeed, if not, why would you even have an accessor for this pointer?) and thus this non-const returned pointer can basically always be used to violate logical constness.To put this another way, consider oshima's example code, but imagine that the implementation of HTMLElement does not in fact include a parent HTMLElement*, but simply has some pointer to the top-level document. parent() is then implemented by walking the tree to find the parent. In this case, the returned parent pointer is not part of the child's state, so one might assume that the access pattern Gregg describes is OK. But the usage in oshima's example shows that logical constness is still violated once the pointer is returned. Generalize this, and you will understand why after some discussion we eventually concluded that returning a non-const pointer from a const accessor is basically never OK.I realize my message only went to oshima. Anyway, I disagree strongly with this rule being applied always.There are legitimate cases where an object and its owned state are const, but a parent/owning object can change its state without modifying the original object. It should be able to do so without requiring a const_cast.For example, an object A can have a parent B that keeps data associated with A in a map keyed with object A. It's perfectly valid to have A::parent() be const, but return a non-const B*, and do a->parent()->set_data(a, 3).const is for the compiler to do optimizations. You can use it to do some safety checks in code where it makes sense, but don't overdo it.
I realize my message only went to oshima. Anyway, I disagree strongly with this rule being applied always.There are legitimate cases where an object and its owned state are const, but a parent/owning object can change its state without modifying the original object. It should be able to do so without requiring a const_cast.For example, an object A can have a parent B that keeps data associated with A in a map keyed with object A. It's perfectly valid to have A::parent() be const, but return a non-const B*, and do a->parent()->set_data(a, 3).
const is for the compiler to do optimizations.
You can use it to do some safety checks in code where it makes sense, but don't overdo it.
Brett
When you define awhole object 'const', then the compiler can assume it never changes.
That is, in:
const MyObject obj;
int i = obj.non_mutable_field;
DoStuff(&obj);
if (i == obj.non_mutable_field) {
...
}
The compiler is free to optimize away the equality check, even if
DoStuff() uses const_cast to modify its argument.
Use const correctly. If your function is logically const, add a const. If it's not, leave it off. It doesn't seem like a big deal to think about whether const means the right thing for your case. I don't think we need to have a big style thread about every case like this.
On Wed, Jun 6, 2012 at 3:00 PM, Brett Wilson <bre...@chromium.org> wrote:
On Wed, Jun 6, 2012 at 2:53 PM, Antoine Labour <pi...@google.com> wrote:On Wed, Jun 6, 2012 at 2:36 PM, Peter Kasting <pkas...@chromium.org> wrote:On Wed, Jun 6, 2012 at 1:27 PM, oshima <osh...@chromium.org> wrote:I received a concern about making this strict rule because there are some cases that returned pointer is not considereda part of the state of the object, so I'll make it just a strong recommendation (like const accessor in google style guide) withclear explanation.This confusion is actually part of why we have this rule. The problem is that in general, _all_ returned pointers are "part of the state" because the issue is not whether they're members of the const object, but whether there is anything in the transitive closure of everything accessible from the returned pointer that allows you to affect something that the const object sees. The answer to this question is practically always "yes" (indeed, if not, why would you even have an accessor for this pointer?) and thus this non-const returned pointer can basically always be used to violate logical constness.To put this another way, consider oshima's example code, but imagine that the implementation of HTMLElement does not in fact include a parent HTMLElement*, but simply has some pointer to the top-level document. parent() is then implemented by walking the tree to find the parent. In this case, the returned parent pointer is not part of the child's state, so one might assume that the access pattern Gregg describes is OK. But the usage in oshima's example shows that logical constness is still violated once the pointer is returned. Generalize this, and you will understand why after some discussion we eventually concluded that returning a non-const pointer from a const accessor is basically never OK.I realize my message only went to oshima. Anyway, I disagree strongly with this rule being applied always.There are legitimate cases where an object and its owned state are const, but a parent/owning object can change its state without modifying the original object. It should be able to do so without requiring a const_cast.For example, an object A can have a parent B that keeps data associated with A in a map keyed with object A. It's perfectly valid to have A::parent() be const, but return a non-const B*, and do a->parent()->set_data(a, 3).const is for the compiler to do optimizations. You can use it to do some safety checks in code where it makes sense, but don't overdo it.As I've said in other threads, I don't think we need to add all of these kinds of things to the style guide.Use const correctly. If your function is logically const, add a const. If it's not, leave it off.
It doesn't seem like a big deal to think about whether const means the right thing for your case. I don't think we need to have a big style thread about every case like this.+1
Do people actually debate the issue of logical constness with you?
If you're using the style guide to settle debates, then yes, that's useful.
I'd be disappointed if people actually debate this very much, mod some corner exceptional cases discussed earlier in the thread. Are all these instances corner cases like that?
If you're using the style guide to settle debates, then yes, that's useful.That is my goal here. I don't know about oshima's.
I don't really care what the outcome of this debate is. However, it seems odd to add a style rule that things like scoped_ptr don't even follow.
Actual debate might be rare, but it's somewhat common for someone to ask "Why is that better?". It's helpful to have a canonical resource to link to.I point them to Effective C++ Item 3 where Scott Meyers educates people on logical constness.
I don't really care what the outcome of this debate is. However, it seems odd to add a style rule that things like scoped_ptr don't even follow.
On Wed, Jun 6, 2012 at 5:32 PM, Daniel Cheng <dch...@chromium.org> wrote:I don't really care what the outcome of this debate is. However, it seems odd to add a style rule that things like scoped_ptr don't even follow.
This will be strong recommendation but not strict rule and there will be some exceptions.
On Wed, Jun 6, 2012 at 5:32 PM, Daniel Cheng <dch...@chromium.org> wrote:I don't really care what the outcome of this debate is. However, it seems odd to add a style rule that things like scoped_ptr don't even follow.
This will be strong recommendation but not strict rule and there will be some exceptions.For example, bind helper is using multiple inheritance, but it doesn't mean multiple inheritance should be allowed in general.
I often am pointing out parts of the style guide that people don't know. If your hope is to prevent problems from occurring in the first place, I think it's naive to assume that the addition of a new rule in the style guide is going to actually change anything. Do people actually debate the issue of logical constness with you? If you're using the style guide to settle debates, then yes, that's useful. I'd be disappointed if people actually debate this very much, mod some corner exceptional cases discussed earlier in the thread. Are all these instances corner cases like that?Actual debate might be rare, but it's somewhat common for someone to ask "Why is that better?". It's helpful to have a canonical resource to link to.I point them to Effective C++ Item 3 where Scott Meyers educates people on logical constness.
I often am pointing out parts of the style guide that people don't know. If your hope is to prevent problems from occurring in the first place, I think it's naive to assume that the addition of a new rule in the style guide is going to actually change anything. Do people actually debate the issue of logical constness with you? If you're using the style guide to settle debates, then yes, that's useful. I'd be disappointed if people actually debate this very much, mod some corner exceptional cases discussed earlier in the thread. Are all these instances corner cases like that?Actual debate might be rare, but it's somewhat common for someone to ask "Why is that better?". It's helpful to have a canonical resource to link to.I point them to Effective C++ Item 3 where Scott Meyers educates people on logical constness.Sorry, but I don't get the point. You concerned that the style guide is loo large, yet you recommend to read a book that is way larger?I disagree that "the style guide is too large" is valid reason not to extended it. It value is in being clear, rather than being short guide line.If I have to pick, "long, but clear style guide" vs "ambiguous, but short style guide", I'd pick former.
On Wed, Jun 6, 2012 at 10:23 PM, oshima <osh...@chromium.org> wrote:On Wed, Jun 6, 2012 at 5:32 PM, Daniel Cheng <dch...@chromium.org> wrote:I don't really care what the outcome of this debate is. However, it seems odd to add a style rule that things like scoped_ptr don't even follow.
This will be strong recommendation but not strict rule and there will be some exceptions.This makes it not very useful, since the style guide should have (few) rules that are easy to follow. If it becomes a judgement call, then it might as well not be there.
It's also not clear to me why, if this would be helpful, it's not in the Google style guide. Sticking as closely as possible to it is very valuable, and the bar to diverge should be very high. IMO it should be to stop serious bugs, which I don't see this helping against.