www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Const transitivity is bad sometimes

reply naryl <cy ngs.ru> writes:
For example, I have this piece of (useless) code:

http://paste.dprogramming.com/dpmmwnah

If there were more subscribers the same message would be sent to every one  
of them. And there may be several messages, carrying the same notifier as  
their data. While compiling this I got the following errors (DMD 2.009):

main.d(28): function main.SystemShutdownNotifier.addSubscriber  
(Subscriber) does not match parameter types (Subscriber)
main.d(28): Error: (cmd.notifier).addSubscriber can only be called on a  
mutable object, not const(SystemShutdownNotifier)

I know. Notifier has become const because const is transitive, but in this  
example I don't need transitivity. I can't even think of a workaround for  
that. Maybe someone can help?
Jan 11 2008
next sibling parent reply Jason House <jason.james.house gmail.com> writes:
naryl wrote:

 For example, I have this piece of (useless) code:
 
 http://paste.dprogramming.com/dpmmwnah
 
 If there were more subscribers the same message would be sent to every one
 of them. And there may be several messages, carrying the same notifier as
 their data. While compiling this I got the following errors (DMD 2.009):
 
 main.d(28): function main.SystemShutdownNotifier.addSubscriber
 (Subscriber) does not match parameter types (Subscriber)
 main.d(28): Error: (cmd.notifier).addSubscriber can only be called on a
 mutable object, not const(SystemShutdownNotifier)
 
 I know. Notifier has become const because const is transitive, but in this
 example I don't need transitivity. I can't even think of a workaround for
 that. Maybe someone can help?

I think this is the classic sort of problem people have complained about with const transitivity. I don't know what people have suggested as the workaround for this. Personally, I've been thinking it'd be nice to mark objects with something that says "I'll write to this, but will never read from it".
Jan 14 2008
parent reply naryl <cy ngs.ru> writes:
On Mon, 14 Jan 2008 17:01:27 +0300, Jason House  
<jason.james.house gmail.com> wrote:

 naryl wrote:

 For example, I have this piece of (useless) code:

 http://paste.dprogramming.com/dpmmwnah

 If there were more subscribers the same message would be sent to every  
 one
 of them. And there may be several messages, carrying the same notifier  
 as
 their data. While compiling this I got the following errors (DMD 2.009):

 main.d(28): function main.SystemShutdownNotifier.addSubscriber
 (Subscriber) does not match parameter types (Subscriber)
 main.d(28): Error: (cmd.notifier).addSubscriber can only be called on a
 mutable object, not const(SystemShutdownNotifier)

 I know. Notifier has become const because const is transitive, but in  
 this
 example I don't need transitivity. I can't even think of a workaround  
 for
 that. Maybe someone can help?

I think this is the classic sort of problem people have complained about with const transitivity. I don't know what people have suggested as the workaround for this. Personally, I've been thinking it'd be nice to mark objects with something that says "I'll write to this, but will never read from it".

I've found several similar cases. It happens when short-lived invariant object has reference to long-lived mutable object, but not the object itself. When one object creates, contains and finalizes another it is logical to make contained object invariant if container is invariant. But when (as in example) invariant Message is used only to deliver notifier to several subscribers, transitive const doesn't fit. Of course I can cast it away, but on http://www.digitalmars.com/d/const3.html it states that "modification after casting away const" [is] "undefined behavior".
Jan 15 2008
parent Robert Fraser <fraserofthenight gmail.com> writes:
naryl wrote:
 I've found several similar cases. It happens when short-lived invariant 
 object has reference to long-lived mutable object, but not the object 
 itself. When one object creates, contains and finalizes another it is 
 logical to make contained object invariant if container is invariant. 
 But when (as in example) invariant Message is used only to deliver 
 notifier to several subscribers, transitive const doesn't fit. Of course 
 I can cast it away, but on http://www.digitalmars.com/d/const3.html it 
 states that "modification after casting away const" [is] "undefined 
 behavior".

I think in this case it should be okay as long as at least one mutable reference to the object exists, since the referenced object can't be treated as invariant.
Jan 15 2008
prev sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
"naryl" wrote
 For example, I have this piece of (useless) code:

 http://paste.dprogramming.com/dpmmwnah

 If there were more subscribers the same message would be sent to every one 
 of them. And there may be several messages, carrying the same notifier as 
 their data. While compiling this I got the following errors (DMD 2.009):

 main.d(28): function main.SystemShutdownNotifier.addSubscriber 
 (Subscriber) does not match parameter types (Subscriber)
 main.d(28): Error: (cmd.notifier).addSubscriber can only be called on a 
 mutable object, not const(SystemShutdownNotifier)

 I know. Notifier has become const because const is transitive, but in this 
 example I don't need transitivity. I can't even think of a workaround for 
 that. Maybe someone can help?

This is an example of something that should be re-designed. It looks more like the subscriber should contain the notifier, not the message. However, I don't see where this stuff is used, so I'm not sure how you designed the rest of it. Another option is to build in the invariance in the class itself. So instead of making the whole message invariant, just make the portions that aren't going to change invariant (your example really doesn't have any other members, but I'm assuming normal messages have other data that you want to be invariant?), and then you are free to modify the notifier. -Steve
Jan 16 2008
parent naryl <cy ngs.ru> writes:
On Wed, 16 Jan 2008 21:45:43 +0300, Steven Schveighoffer  
<schveiguy yahoo.com> wrote:

 "naryl" wrote
 For example, I have this piece of (useless) code:

 http://paste.dprogramming.com/dpmmwnah

 If there were more subscribers the same message would be sent to every  
 one
 of them. And there may be several messages, carrying the same notifier  
 as
 their data. While compiling this I got the following errors (DMD 2.009):

 main.d(28): function main.SystemShutdownNotifier.addSubscriber
 (Subscriber) does not match parameter types (Subscriber)
 main.d(28): Error: (cmd.notifier).addSubscriber can only be called on a
 mutable object, not const(SystemShutdownNotifier)

 I know. Notifier has become const because const is transitive, but in  
 this
 example I don't need transitivity. I can't even think of a workaround  
 for
 that. Maybe someone can help?

This is an example of something that should be re-designed. It looks more like the subscriber should contain the notifier, not the message. However, I don't see where this stuff is used, so I'm not sure how you designed the rest of it. Another option is to build in the invariance in the class itself. So instead of making the whole message invariant, just make the portions that aren't going to change invariant (your example really doesn't have any other members, but I'm assuming normal messages have other data that you want to be invariant?), and then you are free to modify the notifier. -Steve

Thanks! I forgot that message is intended to be invariant-only. Then I can build it in the class and leave notifier mutable.
Jan 16 2008