Casting from const to non-const

Started by
26 comments, last by Kest 18 years, 7 months ago
I've just recently realized it's possible to cast to override a const trait on a variable type. Seems a little too easy in fact..? Anyway, here's the situation I'm in. My characters allow const access to their inventory. The inventory menu uses this access to set up lists and such for the interface. But when it comes time to signal the character to make inventory changes, I need to send the equip/unequip item pointers to the character task function. The funny thing is that these pointers are const, and the character obviously can't change equipped status on them. So they need a non-const pointer to the item. From my knowledge, there are two things I could do. One is to simply cast it to non-const. But damn that seems like a backwards thing to do. The other would be to search for the item in their inventory locations and find the same item - obtaining a normal non-const pointer. That seems pretty backwards too! Any suggestions?
Advertisement
You might be better off to use cast it to a non-const. It'd probably take up less time to just cast it then to do a search for the item in the inventory then obtain the non-const pointer. The difference is probably unnoticable to the user.
Speed isn't that much of a concern. The game is single player and the menu will pause the action. But saftey isn't really a concern either, considering a debug-only inventory-search can be implimented even on top of the cast.

I guess there's no harm in casting it. Does this situation not come up often? The only way around it would be to allow non-const inventory access.

Thanks for your time :)
99% of the time if you are casting away const that you declared in your own application than you should rethink the design as this is a red flag. The reason for casting away const is not so you can throw out your own const contracts, but to be compatible with other libraries that don't follow proper constness and/or C libraries.
Quote:Original post by Kest
Speed isn't that much of a concern. The game is single player and the menu will pause the action. But saftey isn't really a concern either, considering a debug-only inventory-search can be implimented even on top of the cast.

I guess there's no harm in casting it. Does this situation not come up often? The only way around it would be to allow non-const inventory access.

Thanks for your time :)


It's usually an indication that something is const that shouldn't have been const.

The solutions that come to mind (realize it's 2AM):
1) Does the equipment need to know whether or not it's equipped? If not, find some other means. For example, "move" an equipped item from the inventory to where it's equipped. There, now it can be const.

2) Realize the intent of each function. You don't intend for the character class to modify the objected you're passing it, that's just a means to indicate which object in the character's inventory you want him to equip. What if you passed him something not in his inventory? Thus, you should look it up in his inventory anyway.

3) Or, realize the intent of const. If the menu needs to modify the object, then the object shouldn't be const in the first place. Having to pass the object as a non-const pointer counts as having to modify the object.

4) Use the mutable keyword so that you can change the relevant state of the equipment even if it's const.

5) Use const_cast so that you can modify the const object.

(4) and (5) seem like bad ideas. Sort of like you're pretending to be const-correct but not really. Although, (4) doesn't seem nearly so bad as (5) and some might argue that's why they included the mutable keyword (whereas const_cast was added to deal with libraries that don't use const where appropriate).
Quote:Original post by Saruman
99% of the time if you are casting away const that you declared in your own application than you should rethink the design as this is a red flag. The reason for casting away const is not so you can throw out your own const contracts, but to be compatible with other libraries that don't follow proper constness and/or C libraries.


C has had const since C89. Only libraries written for K&R and older versions of C have an excuse for not following proper constness.
Quote:Original post by Anonymous Poster
Quote:Original post by Saruman
99% of the time if you are casting away const that you declared in your own application than you should rethink the design as this is a red flag. The reason for casting away const is not so you can throw out your own const contracts, but to be compatible with other libraries that don't follow proper constness and/or C libraries.


C has had const since C89. Only libraries written for K&R and older versions of C have an excuse for not following proper constness.

Oh I realize that C has had const in the standard, but there are many C programmers and libraries out there that are not following proper constness, I have actually seen it a lot.
Quote:Original post by Anonymous Poster
It's usually an indication that something is const that shouldn't have been const.

I don't think that's true in my case. Equipment is pretty dynamic when characters are using them. They track ammunition counts, heat levels, and a few other dynamic states. So characters need non-const equipment. And the inventory doesn't modify the items. The only situation where they need non-const items is when telling the character what items to equip - which isn't needing non-const access, but the character needs to equip the items. It would have to make a const to non-const transition somewhere along the line to be equipped.

Quote:Original post by Saruman
99% of the time if you are casting away const that you declared in your own application than you should rethink the design as this is a red flag. The reason for casting away const is not so you can throw out your own const contracts, but to be compatible with other libraries that don't follow proper constness and/or C libraries.

I'm not sure you understand what I'm saying. I'm not throwing out const. Imagine a simple list that gives only const access to its non-const nodes. What if the list could perform a task, such as 'remove', which obviously needs non-const access. The item could even have links to neighboring nodes and a parent link to the list itself - making it obvious that the list owns it. How do you signal to the list to remove an item which you have a const pointer to?

The only possible items the inventory can contain are the character's items. I could easily give all items unique IDs, pass that to the character from the inventory menu and have them search their inventories for it. Likewise, I can use the const pointer just like an ID and search for that. But is there really a point? If I know it's there and I know I have a non-const version of it, it seems pretty silly.

Don't get me wrong, I'm all open to suggestions for rethinking the design.
Quote:Original post by Kest
Imagine a simple list that gives only const access to its non-const nodes. What if the list could perform a task, such as 'remove', which obviously needs non-const access. The item could even have links to neighboring nodes and a parent link to the list itself - making it obvious that the list owns it. How do you signal to the list to remove an item which you have a const pointer to?


Why does the list only provide const access? You can overload it to provide both a const and non-const pointer. Better yet, use std::list!

Basically, when you declare your function to accept a const object, you're indicating to the rest of your code that this function will not modify the object, i.e. the object will be in the exact same way after calling the function as it was before it entered the function. If you cannot make this promise, then you need to provide a non-const pointer.

Another solution might be to provide the inventory menu an index of the item, and then it can call various functinos form the character using that index.

HTH
Quote:Original post by Saruman
99% of the time if you are casting away const that you declared in your own application than you should rethink the design as this is a red flag. The reason for casting away const is not so you can throw out your own const contracts, but to be compatible with other libraries that don't follow proper constness and/or C libraries.

I'm not sure you understand what I'm saying. I'm not throwing out const.


He didn't say you were throwing out const, he said you're throwing out your const contract. const is a promise you won't modify the object, but you are modifying the object.

Quote:
Imagine a simple list that gives only const access to its non-const nodes.


Imagine you ask if you can borrow my car to go to the grocery story. Imagine I say "Sure" but don't give you the keys.

Quote:
I can use the const pointer just like an ID and search for that. But is there really a point? If I know it's there and I know I have a non-const version of it, it seems pretty silly.


Do you know that?

const Equipment *e = c1.getFirstInInventory();
c2.equip(e);

By the way, how does the menu access the inventory? Through an iterator? An index? A getNext() function? If an index, that would be ideal to pass back. Also, for what it's worth, it almost sounds like the menu should be doing the equipping, not the character class.

This topic is closed to new replies.

Advertisement