Path: utzoo!utgpu!news-server.csri.toronto.edu!rutgers!usc!wuarchive!uunet!lupine!rfg From: rfg@NCD.COM (Ron Guilmette) Newsgroups: comp.std.c++ Subject: Re: casting "const" to "non-const" Message-ID: <1029@lupine.NCD.COM> Date: 31 Jul 90 22:42:27 GMT References: <56159@microsoft.UUCP> <56163@microsoft.UUCP> Organization: Network Computing Devices, Inc., Mt. View, CA Lines: 95 In article <56163@microsoft.UUCP> jimad@microsoft.UUCP (Jim ADCOCK) writes: >Proposed: > >That when a parameter [including the hidden "this" parameter] is declared >"const", or when the object referenced by a parameter is declared "const", >then it is not legal to modify that which is declared "const" within the >function. Your wording is fuzzy, but I get the idea. Note that for: extern void foobar (const int i); It can't make any difference to an optimizing compiler whether or not the const is in there or not, or whether or not foobar() enforces it strictly. However in the case of: extern void foobar (const int* i); it certainly can make a difference. >This is to say, the trick of casting to a non-const does not >work on a parameter declared as "const." Compilers can flag as an error >these situations. Why so fascist? I prefer warnings in such cases. I can even give you an example where "casting aside const'ness" was indispensible to me on one occasion. Imagine that you have a big program that every so often creates "nodes" (actually structs or classes) of some type. Each time one of these puppies gets created, it gets linked into some larger data-structure consisting of a large set of these things. (Let's just call it a network of "nodes".) Now once these guys are created, they remain essentially constant. So right after they get created and initialized, we totally wipe out any remnant of the original pointers to these guys and from then on use `const*' pointers instead. We pass these around, from routine to routine, throughout this big program, all over the place. Now although 99% of the program is perfectly happy to have the *entire* structures be constant (because no fields are ever modified after initialization) there is one tiny exception. Eventually, we want to print out a list of the contents of each of these "nodes", but we want to make sure that we never print any node more than once. Since the overall data-structure is a network, we (unfortunately) have no easy way to traverse the complete data structure such that we can be assured of only visiting each node one (and only one) time. Whatdaya do? Simple. Add a boolean field to each node called "printed". This gets initialized to false, but whild we are in the printing stage, these fields (in each record) will be set, one-by-one to true. If, during our printing traversal through the data structure, we see a node that has already been "checked off" (i.e. printed == TRUE), we avoid printing that node (redundantly) again. My code (in C) looked kinda like: struct node { const struct node *related1; const struct node *related2; int printed; }; void print_traversal (const struct node *arg) { if ( ! arg->printed) { print (arg); /* Cast aside const'ness */ } print_traversal (arg->related1); print_traversal (arg->related2); } >The reason I propose this restriction on the casting trick is to allow >compilers to correctly optimize code when presented with independently >compiled libraries. To be able to correctly optimize, compilers need to >be able to assume that "const means const" in those libraries. This is already allowed. Read your ANSI C standard. If one uses dirty tricks (like casting away const'ness) the standard sez that your compiler has the right to screw you unless you are very careful. Of course, the standard doesn't use the term "screw you". It prefers "behavior undefined". -- // Ron Guilmette // C++ Entomologist // Internet: rfg@ncd.com uucp: ...uunet!lupine!rfg // Motto: If it sticks, force it. If it breaks, it needed replacing anyway.