Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c++ > #9326 > unrolled thread

which of these 3 casts would you prefer?

Started by"A" <a@a.a>
First post2011-08-25 23:58 +0200
Last post2011-08-26 07:30 -0700
Articles 11 on this page of 51 — 20 participants

Back to article view | Back to comp.lang.c++


Contents

  which of these 3 casts would you prefer? "A" <a@a.a> - 2011-08-25 23:58 +0200
    Re: which of these 3 casts would you prefer? Andrey Tarasevich <andreytarasevich@hotmail.com> - 2011-08-25 16:19 -0700
    Re: which of these 3 casts would you prefer? Robert Wessel <robertwessel2@yahoo.com> - 2011-08-25 18:59 -0500
    Re: which of these 3 casts would you prefer? "Alf P. Steinbach" <alf.p.steinbach:usenet@gmail.com> - 2011-08-26 08:02 +0200
    Re: which of these 3 casts would you prefer? "Duga Chernobyl" <duga_c3@gmx.com> - 2011-08-26 10:05 +0200
      Re: which of these 3 casts would you prefer? "A" <a@a.a> - 2011-08-26 14:40 +0200
        Re: which of these 3 casts would you prefer? Leigh Johnston <leigh@i42.co.uk> - 2011-08-26 13:59 +0100
        Re: which of these 3 casts would you prefer? "Duga Chernobyl" <duga_c3@gmx.com> - 2011-08-26 15:19 +0200
          Re: which of these 3 casts would you prefer? Jorgen Grahn <grahn+nntp@snipabacken.se> - 2011-08-26 21:27 +0000
            Re: which of these 3 casts would you prefer? "Alf P. Steinbach" <alf.p.steinbach:usenet@gmail.com> - 2011-08-27 01:28 +0200
            Re: which of these 3 casts would you prefer? "Duga Chernobyl" <duga_c3@gmx.com> - 2011-08-27 10:23 +0200
              Re: which of these 3 casts would you prefer? Jorgen Grahn <grahn+nntp@snipabacken.se> - 2011-08-27 12:10 +0000
            Re: which of these 3 casts would you prefer? RaZiel <raziel_206_@hotmail.com> - 2011-08-27 21:55 +0200
            Re: which of these 3 casts would you prefer? Miles Bader <miles@gnu.org> - 2011-09-01 08:03 +0900
              Re: which of these 3 casts would you prefer? BGB <cr88192@hotmail.com> - 2011-08-31 23:11 -0700
              Re: which of these 3 casts would you prefer? Jorgen Grahn <grahn+nntp@snipabacken.se> - 2011-09-01 19:34 +0000
                Re: which of these 3 casts would you prefer? Joshua Maurice <joshuamaurice@gmail.com> - 2011-09-01 15:37 -0700
                  Re: which of these 3 casts would you prefer? gwowen <gwowen@gmail.com> - 2011-09-02 00:30 -0700
                    Re: which of these 3 casts would you prefer? Miles Bader <miles@gnu.org> - 2011-09-03 18:26 +0900
        Re: which of these 3 casts would you prefer? Edek <edek.pienkowski@gmail.com> - 2011-08-26 15:29 +0200
        Re: which of these 3 casts would you prefer? BGB <cr88192@hotmail.com> - 2011-08-27 09:35 -0700
          Re: which of these 3 casts would you prefer? Juha Nieminen <nospam@thanks.invalid> - 2011-08-27 18:38 +0000
            Re: which of these 3 casts would you prefer? Noah Roberts <roberts.noah@gmail.com> - 2011-08-27 12:32 -0700
              Re: which of these 3 casts would you prefer? BGB <cr88192@hotmail.com> - 2011-08-27 14:51 -0700
                Re: which of these 3 casts would you prefer? Jorgen Grahn <grahn+nntp@snipabacken.se> - 2011-08-29 14:10 +0000
                  Re: which of these 3 casts would you prefer? BGB <cr88192@hotmail.com> - 2011-08-30 07:23 -0700
              Re: which of these 3 casts would you prefer? Jorgen Grahn <grahn+nntp@snipabacken.se> - 2011-08-29 11:32 +0000
            Re: which of these 3 casts would you prefer? BGB <cr88192@hotmail.com> - 2011-08-27 14:37 -0700
              Re: which of these 3 casts would you prefer? Ian Collins <ian-news@hotmail.com> - 2011-08-28 10:06 +1200
                Re: which of these 3 casts would you prefer? BGB <cr88192@hotmail.com> - 2011-08-27 15:27 -0700
                  Re: which of these 3 casts would you prefer? Ian Collins <ian-news@hotmail.com> - 2011-08-28 10:47 +1200
                  Re: which of these 3 casts would you prefer? Noah Roberts <roberts.noah@gmail.com> - 2011-08-27 15:42 -0700
                  Re: which of these 3 casts would you prefer? Nobody <nobody@nowhere.com> - 2011-08-28 04:15 +0100
              Re: which of these 3 casts would you prefer? Noah Roberts <roberts.noah@gmail.com> - 2011-08-27 15:52 -0700
                Re: which of these 3 casts would you prefer? BGB <cr88192@hotmail.com> - 2011-08-28 01:54 -0700
                  Re: which of these 3 casts would you prefer? Keith H Duggar <duggar@alum.mit.edu> - 2011-09-04 19:16 -0700
              Re: which of these 3 casts would you prefer? Juha Nieminen <nospam@thanks.invalid> - 2011-08-29 18:16 +0000
                Re: which of these 3 casts would you prefer? Noah Roberts <roberts.noah@gmail.com> - 2011-08-29 16:35 -0700
                  Re: which of these 3 casts would you prefer? Nobody <nobody@nowhere.com> - 2011-08-30 04:13 +0100
                  Re: which of these 3 casts would you prefer? Juha Nieminen <nospam@thanks.invalid> - 2011-08-30 06:03 +0000
                Re: which of these 3 casts would you prefer? BGB <cr88192@hotmail.com> - 2011-08-30 07:12 -0700
                  Re: which of these 3 casts would you prefer? Juha Nieminen <nospam@thanks.invalid> - 2011-08-31 06:16 +0000
                    Re: which of these 3 casts would you prefer? BGB <cr88192@hotmail.com> - 2011-09-01 03:05 -0700
                      Re: which of these 3 casts would you prefer? Juha Nieminen <nospam@thanks.invalid> - 2011-09-01 07:00 +0000
                        Re: which of these 3 casts would you prefer? BGB <cr88192@hotmail.com> - 2011-08-31 13:21 -0700
            Re: which of these 3 casts would you prefer? Jorgen Grahn <grahn+nntp@snipabacken.se> - 2011-08-28 19:30 +0000
        Re: which of these 3 casts would you prefer? Noah Roberts <roberts.noah@gmail.com> - 2011-08-27 12:19 -0700
          Re: which of these 3 casts would you prefer? Dombo <dombo@disposable.invalid> - 2011-08-28 12:08 +0200
          Re: which of these 3 casts would you prefer? Jorgen Grahn <grahn+nntp@snipabacken.se> - 2011-08-28 19:44 +0000
            Re: which of these 3 casts would you prefer? Noah Roberts <roberts.noah@gmail.com> - 2011-08-28 13:41 -0700
      Re: which of these 3 casts would you prefer? Anand Hariharan <mailto.anand.hariharan@gmail.com> - 2011-08-26 07:30 -0700

Page 3 of 3 — ← Prev page 1 2 [3]


#9480

FromBGB <cr88192@hotmail.com>
Date2011-08-30 07:12 -0700
Message-ID<j3irdi$spq$1@news.albasani.net>
In reply to#9441
On 8/29/2011 11:16 AM, Juha Nieminen wrote:
> BGB<cr88192@hotmail.com>  wrote:
>>>     The major problem in C is not the lack of dynamic binding. It's the
>>> lack of RAII and templates. (And, to some extent, exceptions.)
>>
>> RAII normally only really deals with cases which can be dealt with
>> manually though (apart from exceptions, which also don't exist in C, and
>> things like longjmp are rarely used).
>
>    You write as if the lack of RAII was only a minor inconvenience. I don't
> agree with that.
>
>    One of the major problems with that lack, which means that resources
> have to be managed manually, is that this management burden is "contagious".
> With that I mean that if you have a type which needs to be destroyed
> manually, that requirement is transferred to any other type that wants
> to use that type as a member. (In other words, if you have eg. a struct
> that needs to be constructed and destructed by explicitly calling some
> functions, if you want to use that struct as a member of another struct,
> you need to write equivalent construction/destruction functions for *that*
> struct too, and the need to manually call them is "inherited" by that
> struct. And so on. It can become quite complicated and burdensome.)
>

well, this comes down to coding style:
most data types of this sort are not allocated/freed directly, but are 
allocated/freed via function calls.

say:
FOO_Context *ctx;

ctx=FOO_NewContext(...);
...
FOO_FreeContext(ctx);

however, rarely does this seem like a big deal.

also, the matter of multiple entry/exit points and releasing things also 
has a typically straightforward solution:
if for some function it becomes awkward, it means the function is 
probably doing too much and needs to be broken down into smaller ones.

typically, 5-25 lines is a good limit for a function size, as well as 
the usual practice that a function only does a single conceptual 
operation (as opposed to a function which does "this, that, and this 
other thing"...).


>    It also makes generic programming a lot more difficult. If you make,
> for example, a generic container, you have no way of knowing whether
> the elements need to be properly destroyed before freeing them or not.
> If you want your container to support such elements, you have to offer
> some kind of construction/destruction paradigm, which can be inconvenient,
> and in the case of elements that don't need it, needless overhead.
>

typical answers:
one generally doesn't use generic containers (containers are created on 
an as-needed basis);
typically containers are homogenous;
for complex non-uniform data types, typically a vtable and/or a pointer 
to a destructor function can be used.


this is again why, as noted before, one memorizes/internalizes things 
like hashing, linked lists, and sorting algorithms, as one often needs 
to deal with them on a fairly regular basis (one memorizes basic 
algorithms much as one memorizes things like lists of API functions, ...).

not that it has to be done in some sort of rote/school style way, but 
one tends to memorize things after dealing with them a few times.


>> also, several other major languages, such as Java and C#, also lack RAII
>> (with exceptions, this behavior is handled by the use of a "finally"
>> clause).
>
>    This is actually a problem in Java because if you have to manage any
> resource other than memory, you run into the problem of having to free
> the resource manually (at least if the resource should be freed as soon
> as possible; the finalizer mechanism in Java doesn't guarantee when
> destructors will be called, or even that they will be called at all).
>
>    The 'finally' block only handles a subset of cases that RAII does, and
> it's nevertheless more burdensome because you have to implement it
> manually. (At least it's safer than anything in C, which is a plus.)

potentially...

but then again, a typical pattern in C becomes:
int BAR_Sub_DoSomething(...)
{
     FOO_Context *ctx;
     int i;

     ctx=FOO_NewContext(...);
     ...
     i=FOO_GetFinalValue(ctx);
     FOO_FreeContext(ctx);
     return(i);
}

then the form of a function becomes itself a convention.

if success/failure status is involved, typically this is handled either 
with "if()" blocks, or folding the next step into its own function (the 
use of "goto" is nasty and so typically not done).


in Java, the usual strategy is to introduce ones' own release methods 
(rather than trying to rely on finally).


for some data types, it is also common to create ones' own mini 
allocator/free system.

public class Foo
{
     private static Foo freeList;
     private Foo next;

     public static final Foo newFoo()
     {
         Foo tmp;
         if(freeList)
         {
             tmp=freeList;
             freeList=tmp.next;
             tmp.next=null;
             return tmp;
         }
         tmp=new Foo();
         return tmp;
     }

     public static final void freeFoo(Foo tmp)
     {
         ...
         tmp.next=freeList;
         freeList=tmp;
     }

     public void free()
     {
         freeFoo(this);
     }
}


as well as things like:
Foo obj=Foo.newFoo();
try {
     ...
}finally {
     obj.free();
}

because, unlike some people seem to claim, the GC is a good deal more 
hit-or-miss in practice when it comes to non-trivial usage patterns (and 
GC cycles are not always free).



for my own scripting language, I have a delete keyword (partly itself 
inherited from ActionScript, which presumably got it from C++).

however, sadly, at the moment there is no good way to prove that no one 
tries to access an object after freeing it (a potential safety/security 
concern), but it is a tradeoff (however, like Flash, in my language it 
is not required that the VM accept the request to delete something, and 
it may potentially reject it in some cases, although at the moment it 
will actually just free whatever is given to it provided the code has 
the needed permissions).

granted, the addition of VM-level permissions checking (using a 
POSIX-style model) was itself a subject of debate (others argued for 
sandboxing and trying to make sure that sandboxed code could never get 
any references to secure objects, worrying that any sort of security 
checking would be too slow/complex/... to be usable).


or such...

[toc] | [prev] | [next] | [standalone]


#9538

FromJuha Nieminen <nospam@thanks.invalid>
Date2011-08-31 06:16 +0000
Message-ID<4e5dd1d6$0$4380$7b1e8fa0@news.nbl.fi>
In reply to#9480
BGB <cr88192@hotmail.com> wrote:
> On 8/29/2011 11:16 AM, Juha Nieminen wrote:
>>    One of the major problems with that lack, which means that resources
>> have to be managed manually, is that this management burden is "contagious".
>> With that I mean that if you have a type which needs to be destroyed
>> manually, that requirement is transferred to any other type that wants
>> to use that type as a member. (In other words, if you have eg. a struct
>> that needs to be constructed and destructed by explicitly calling some
>> functions, if you want to use that struct as a member of another struct,
>> you need to write equivalent construction/destruction functions for *that*
>> struct too, and the need to manually call them is "inherited" by that
>> struct. And so on. It can become quite complicated and burdensome.)
>>
> 
> well, this comes down to coding style:
> most data types of this sort are not allocated/freed directly, but are 
> allocated/freed via function calls.

  How does that change what I said? It doesn't matter if it's allocated
and freed directly or via function calls. (Heck, malloc() and free() *are*
function calls.)

  My point is that this manual construction/destruction requirement is
"inherited" by anything that wants to use those types. For example, if
you create a new struct that has such a type as a member, this struct
will now also have to be constructed/destructed manually, and so on.
The language offers no means to automatize and hide this in any way.

>>    It also makes generic programming a lot more difficult. If you make,
>> for example, a generic container, you have no way of knowing whether
>> the elements need to be properly destroyed before freeing them or not.
>> If you want your container to support such elements, you have to offer
>> some kind of construction/destruction paradigm, which can be inconvenient,
>> and in the case of elements that don't need it, needless overhead.
>>
> 
> typical answers:
> one generally doesn't use generic containers (containers are created on 
> an as-needed basis);
> typically containers are homogenous;

  Containers being homogeneous has nothing to do with genericness. A container
being generic means that you can use it with any type, rather than it being
fixed to a single hard-coded type, even if the container is homogeneous.

  Even if the container is hard-coded for one single type, if that type
requires construction and destruction, it makes the implementation of the
container more complicated and more error-prone.

> this is again why, as noted before, one memorizes/internalizes things 
> like hashing, linked lists, and sorting algorithms, as one often needs 
> to deal with them on a fairly regular basis (one memorizes basic 
> algorithms much as one memorizes things like lists of API functions, ...).

  Having to implement the same algorithms over and over has never been a
good programming practice. That's why generic programming is such a great
aid in this.

> then the form of a function becomes itself a convention.

  You see, these coding conventions exist solely because of the deficiencies
of the language, rather than because they are good programming practices.
With RAII they become unneeded, and the resulting code becomes simpler,
more straightforward and easier to read.

[toc] | [prev] | [next] | [standalone]


#9578

FromBGB <cr88192@hotmail.com>
Date2011-09-01 03:05 -0700
Message-ID<j3mb8b$rcj$1@news.albasani.net>
In reply to#9538
On 8/30/2011 11:16 PM, Juha Nieminen wrote:
> BGB<cr88192@hotmail.com>  wrote:
>> On 8/29/2011 11:16 AM, Juha Nieminen wrote:
>>>     One of the major problems with that lack, which means that resources
>>> have to be managed manually, is that this management burden is "contagious".
>>> With that I mean that if you have a type which needs to be destroyed
>>> manually, that requirement is transferred to any other type that wants
>>> to use that type as a member. (In other words, if you have eg. a struct
>>> that needs to be constructed and destructed by explicitly calling some
>>> functions, if you want to use that struct as a member of another struct,
>>> you need to write equivalent construction/destruction functions for *that*
>>> struct too, and the need to manually call them is "inherited" by that
>>> struct. And so on. It can become quite complicated and burdensome.)
>>>
>>
>> well, this comes down to coding style:
>> most data types of this sort are not allocated/freed directly, but are
>> allocated/freed via function calls.
>
>    How does that change what I said? It doesn't matter if it's allocated
> and freed directly or via function calls. (Heck, malloc() and free() *are*
> function calls.)
>
>    My point is that this manual construction/destruction requirement is
> "inherited" by anything that wants to use those types. For example, if
> you create a new struct that has such a type as a member, this struct
> will now also have to be constructed/destructed manually, and so on.
> The language offers no means to automatize and hide this in any way.
>

well, when you create the new type / structs and functions, you wrap the 
old ones.

so, no big deal, one creates/destroys objects in a similar way, 
regardless of how many levels are involved.

alternatively, one can treat them all as the root type by using function 
pointers to handle the case of the destruction of subtypes:

struct FOO_SomeType_s {
void *data;	//member
void (*deinit)(FOO_SomeType *self);
...
};

then:
void FOO_FreeSomeType(FOO_SomeType *self)
{
     if(self->deinit)
         self->deinit(self);
     free(self);
}

in practice, it is all "not really a big deal".

for added safety though, one can use a garbage collector in place of 
malloc/free, and give the GC the ability to call destructors, creating a 
mechanism vaguely similar to Java's finalizer system.


>>>     It also makes generic programming a lot more difficult. If you make,
>>> for example, a generic container, you have no way of knowing whether
>>> the elements need to be properly destroyed before freeing them or not.
>>> If you want your container to support such elements, you have to offer
>>> some kind of construction/destruction paradigm, which can be inconvenient,
>>> and in the case of elements that don't need it, needless overhead.
>>>
>>
>> typical answers:
>> one generally doesn't use generic containers (containers are created on
>> an as-needed basis);
>> typically containers are homogenous;
>
>    Containers being homogeneous has nothing to do with genericness. A container
> being generic means that you can use it with any type, rather than it being
> fixed to a single hard-coded type, even if the container is homogeneous.
>
>    Even if the container is hard-coded for one single type, if that type
> requires construction and destruction, it makes the implementation of the
> container more complicated and more error-prone.
>

this seems like hair-splitting IMO.

only one of 2 possibilities exist:
the container is responsible for destroying its contents, in which case 
it will do so;
it will not be responsible for doing so, and it will be the 
responsibility of the client to destroy all container contents and then 
destroy the container.


IMO probably one of the most common "containers" in C is the internally 
linked-list (every member points to the next one) in which in the common 
case destroying the container and destroying its contents are equivalent.

cur=first;
while(cur)
{
     nxt=cur->next;
     FOO_FreeFoo(cur);
     cur=nxt;
}



>> this is again why, as noted before, one memorizes/internalizes things
>> like hashing, linked lists, and sorting algorithms, as one often needs
>> to deal with them on a fairly regular basis (one memorizes basic
>> algorithms much as one memorizes things like lists of API functions, ...).
>
>    Having to implement the same algorithms over and over has never been a
> good programming practice. That's why generic programming is such a great
> aid in this.
>

but, it is common practice, no different from a manual transmission, or 
filling out and filing paperwork, ...


like "just do it", "doesn't matter if it is clean or elegant, just make 
it work", ...


>> then the form of a function becomes itself a convention.
>
>    You see, these coding conventions exist solely because of the deficiencies
> of the language, rather than because they are good programming practices.
> With RAII they become unneeded, and the resulting code becomes simpler,
> more straightforward and easier to read.

well, as noted, it is not C's job to be programmer friendly.

usually, it is used for things like implementing back-end libraries, 
often with the front-end application-development done in a different 
language, for example: C++, Java, C#, Ruby, Python, Lua, or some other 
custom-designed language.


but, one may develop their libraries in C, since it may not be known in 
advance which language may need to interface with the library code, and 
in most ways C is the least common denominator (and for many types of 
library, using C++ will not bring so much benefit internally if the 
external API has to be C-like anyways).

[toc] | [prev] | [next] | [standalone]


#9582

FromJuha Nieminen <nospam@thanks.invalid>
Date2011-09-01 07:00 +0000
Message-ID<4e5f2d9c$0$2816$7b1e8fa0@news.nbl.fi>
In reply to#9578
BGB <cr88192@hotmail.com> wrote:
> but, it is common practice, no different from a manual transmission, or 
> filling out and filing paperwork, ...
> 
> well, as noted, it is not C's job to be programmer friendly.

  I think these summarize perfectly the kind of mentality that the
language produces, and the reason why I hate the language so much.

  C++ might not be as "programmer friendly" as many other high-level
languages, but at least it offers significantly more tools to aid the
programmer *without* the compromises of those higher-level languages
(such as increased memory consumption or the requirement of a very
complex runtime environment and JIT compiler to make the program even
acceptably fast, and which often do not exist in most systems, especially
the embedded ones.)

  If someone wants to create big projects in C, even if C++ or other
languages would be perfecly good for the job, that's fine. However,
when these same people start preaching how the defects of the language
are "normal" and "not a big deal", rather than "yeah, it's bad, but you
just have to live with it", that's rationalizing.

[toc] | [prev] | [next] | [standalone]


#9587

FromBGB <cr88192@hotmail.com>
Date2011-08-31 13:21 -0700
Message-ID<j3nfb6$g6d$1@news.albasani.net>
In reply to#9582
On 9/1/2011 12:00 AM, Juha Nieminen wrote:
> BGB<cr88192@hotmail.com>  wrote:
>> but, it is common practice, no different from a manual transmission, or
>> filling out and filing paperwork, ...
>>
>> well, as noted, it is not C's job to be programmer friendly.
>
>    I think these summarize perfectly the kind of mentality that the
> language produces, and the reason why I hate the language so much.
>
>    C++ might not be as "programmer friendly" as many other high-level
> languages, but at least it offers significantly more tools to aid the
> programmer *without* the compromises of those higher-level languages
> (such as increased memory consumption or the requirement of a very
> complex runtime environment and JIT compiler to make the program even
> acceptably fast, and which often do not exist in most systems, especially
> the embedded ones.)
>

yes, well, this is true at least.


>    If someone wants to create big projects in C, even if C++ or other
> languages would be perfecly good for the job, that's fine. However,
> when these same people start preaching how the defects of the language
> are "normal" and "not a big deal", rather than "yeah, it's bad, but you
> just have to live with it", that's rationalizing.

I am not entirely sure I see the distinction though.

I have never been claiming here that C is as 
nice/programmer-friendly/... as C++, rather that it is technically 
usable (absent running into big problems which would render it 
"technically unusable", as it seemed some others were trying to assert).

(examples of things I consider "unusable" would be things like trying to 
write an OS kernel purely in standard Java and on generic PC-style 
hardware, but this excludes cases where there is a common and reasonably 
effective workaround).


as noted, I don't actually dislike C++ either, just there are a few 
cases where it isn't ideal either, and as I see it, a lot of my own code 
happens to fall into this case. so, it is a tradeoff...

one sacrifices some level of niceness, to gain certain other features 
and capabilities.

elsewhere, one can sacrifice some of these capabilities (if they are not 
useful in a given case), and gain some nice features.

I think probably each language has found an effective local minima WRT 
its costs, but each has different cost-sets.


it is much like, there are also cases where ASM is the ideal solution, 
and other cases where a higher-level script language (such as JavaScript 
/ Python / Lua / ...) are more ideal.

if something is used outside of its ideal usage domain, then it is 
generally perceived as "worse" than whatever is dominant in the area.


or such...

[toc] | [prev] | [next] | [standalone]


#9412

FromJorgen Grahn <grahn+nntp@snipabacken.se>
Date2011-08-28 19:30 +0000
Message-ID<slrnj5l5qe.gtj.grahn+nntp@frailea.sa.invalid>
In reply to#9362
On Sat, 2011-08-27, Juha Nieminen wrote:
> BGB <cr88192@hotmail.com> wrote:
>> one can also argue that function overloading and operator overloading 
>> are nifty, but rarely have I found this to be a big issue (one can 
>> typically sort-of make due with using short macro names to redirect to 
>> longer operator function names or similar, and with the convention of 
>> using short suffixes to function names to indicate the argument types or 
>> similar...).
>
>   The reason why function and operator overloading is important is not
> because it's "handy" or "convenient" or anything like that. It's because
> it's *necessary* for generic programming.

Well, I think the handiness and convenience are important, too.

When I use C, one of the things I hate the most is coming up with
different names for (for example) is_empty(const Foo*) and
is_empty(Bar*). It really hurts readability.

For example, a C application I work on contains half a dozen linked
list types. They're implemented as just one List_t type, with void* as
values, and we have to write down /as comments/ what type the List_t
is supposed to contain.

I could easily write half a dozen type-safe wrapper structs with
associated next/prev/clear etc operations ... but the operation names
would be too long to be manageable.  They would be

  Subsystem_List_of_FooBar_next()
  Subsystem_List_of_FooBar_prev()
  Subsystem_List_of_FooBar_clear()

and my coworkers would find using those /more/ painful than
the current lack of typing. And they would probably be right.

/Jorgen

-- 
  // Jorgen Grahn <grahn@  Oo  o.   .     .
\X/     snipabacken.se>   O  o   .

[toc] | [prev] | [next] | [standalone]


#9363

FromNoah Roberts <roberts.noah@gmail.com>
Date2011-08-27 12:19 -0700
Message-ID<77f9fdd1-300b-4049-af43-52622f0c3575@x11g2000prk.googlegroups.com>
In reply to#9333
On Aug 26, 5:40 am, "A" <a...@a.a> wrote:
> I do not understand though reluctance to use C style casts.
>
> They can cast to reinterpret_cast but they also try out the weaker cast
> before. It is just automatic way to do what you would do manually - first
> try const_cast, then static_cast and finally reinterpret_cast... yes, it can
> use reinterpret_cast but you would have to use it anyway in a particular
> case where you really need it.
>
> So what's wrong with little automation, providing that you know what you are
> doing with casts?

Perhaps a story would help you understand.

A while back I worked under a guy who used C++ but basically feared
everything about it.  Boy did he love inheritance though.  He used
inheritance as his only method of code reuse.  He created these
gigantic higherarchies that spanned multiple concepts attempting to
tie them together.  Trying to add a new object to this system was a
nightmare because a lot of the time he put in "assert(false); // this
function shouldn't be called" as the base object definition instead of
using pure virtuals.  He did this because his higherarchy was a total
pain in the ass and required you to implement more functions than you
needed.  This of course left one not knowing what functions they
needed to override until running the program and getting an assert.

Eventually this guy quit and moved on to other things and places.
Hopefully he learned something about code design but he was pretty
stubborn.  Once he did, I set about trying to fix the project and put
it into a state that allowed for more code reuse and in which it was
easier to add new behavior.

Did I mention this guy hated everything C++?  This included new-style
casts.  He used C casts everywhere.  He even used them where they were
not necessary.  For example:

class Object
{
public:
  Object* readObjectA(char* c) { return (Object*)ObjectA(c); }
  ... lots more of these ...
};

class ObjectA : public Object { ... };

Now, I did not realize this was going on at the time.  I split all the
various responsibilities that Object had in its interface into
multiple base objects and used multiple inheritance to apply those
interfaces only where they were being used.  Sent the code off to
testing and it starts acting really stupid.  What happened?

Well, the original developer had seen something in the compiler output
like, "cannot convert ObjectA* to Object*, use a reinterpret or c-
style cast," and so he did that instead of realizing he needed to put
these functions in a place that could see the full definition of
ObjectA so that it COULD do that conversion the way it's supposed to.
Believing only in all things C this kind of thing comes completely
natural to him.  Of course, a reinterpret cast to one base among many
is a very bad thing to do.

This problem was trivial to fix but later I ran into further issues.
Because there were C style casts all through the code, we had
opportunity for more issues to come up.  This used the Win32 API and
had a lot of callback functions.  These functions would take a type
number ID (guy hated RTTI and dynamic casting) and then cast to the
appropriate type, having already casted the long or void* to the base
type.  Often this code would assume it's only going to get a certain
subset of objects passed to it because they're the only ones that have
some somewhat related functionality.  If the type wasn't of one it
would assume the other.  It would use c-style casts to do so.  So the
code would promptly cast to the wrong derived class object and start
calling functions on it.  This issue did not turn up until I started
messing with things; it was of course illiciting undefined behavior
all over the place but nobody was the wiser about it because it just
worked, and had worked for 15 years.

Because this guy used c-style casts instead of the appropriate new-
style (or even the inappropriate one), it was quite impractical to
hunt down casts like these and fix them.  They had to turn up as
errors, which occasionally they did when we started adding new objects
to the tree that performed roles that were previously assumed to only
be performed by a group of classes.  We knew that we needed to start
doing dynamic casts for these and shooting out error or exceptions
(which the guy also hated of course) instead of allowing undefined
behavior, but we were stuck because there is no such thing as a
regular expression that will match c-style casts.

This product tree had to be scrapped and redone.  We were stuck with
old interfaces, lacked any amount of I18N and were trying to get into
foreign markets, etc...things that nobody really thought of when the
project started and because of poor design choices and especially
because of an abundant use of C-style casts...the amount of work
necessary to fix the code was astronomical compared to simply redoing
the whole thing.  Cost the company many thousands of dollars to do so
and they're still at it 3 years later.

C-style casts are horrible because they can do anything at any time
without any warning.  One minor code change can turn a static cast
into a reinterpret cast.  You can't hunt these things down because
regular expressions are useless.  The undefined behavior they cause
may or may not turn up at some time in the near future....it may be 2
decades before your code starts crashing in some place utterly
unrelated to the cast in an object that has nothing to do with what is
actually in the memory its using.  NOBODY can keep track of every
place that needs to cast, especially within complex desktop
applications that use casting quite regularly.  Stuff gets lost and
bad things happen.  The new style casts provide a much better method
because they turn up more errors, you'll get a compiler error instead
of successful compile when your static_cast is no longer appropriate,
and can be searched for quite easily.  They should be used for all
cases in which they can be, which is all cases in most projects.

[toc] | [prev] | [next] | [standalone]


#9396

FromDombo <dombo@disposable.invalid>
Date2011-08-28 12:08 +0200
Message-ID<4e5a139d$0$30711$5fc3050@news.tiscali.nl>
In reply to#9363
Op 27-Aug-11 21:19, Noah Roberts schreef:

> C-style casts are horrible because they can do anything at any time
> without any warning.  One minor code change can turn a static cast
> into a reinterpret cast.  You can't hunt these things down because
> regular expressions are useless.  The undefined behavior they cause
> may or may not turn up at some time in the near future....it may be 2
> decades before your code starts crashing in some place utterly
> unrelated to the cast in an object that has nothing to do with what is
> actually in the memory its using.  NOBODY can keep track of every
> place that needs to cast, especially within complex desktop
> applications that use casting quite regularly.  Stuff gets lost and
> bad things happen.  The new style casts provide a much better method
> because they turn up more errors, you'll get a compiler error instead
> of successful compile when your static_cast is no longer appropriate,
> and can be searched for quite easily.  They should be used for all
> cases in which they can be, which is all cases in most projects.

Though I agree with most of what you say here (and your story is all to 
familiar to me), personally I prefer to avoid to having to use casts in 
the first place. When I see code with a lot of casts I tend to get 
nervous. Though C++ style casts are much more precise, I still get 
worried when I see many of them. If casts cannot be avoided (which 
sometimes is the case) the C++ style casts are to be preferred for the 
reasons stated in this thread.

[toc] | [prev] | [next] | [standalone]


#9413

FromJorgen Grahn <grahn+nntp@snipabacken.se>
Date2011-08-28 19:44 +0000
Message-ID<slrnj5l6kc.gtj.grahn+nntp@frailea.sa.invalid>
In reply to#9363
On Sat, 2011-08-27, Noah Roberts wrote:
> On Aug 26, 5:40 am, "A" <a...@a.a> wrote:
>> I do not understand though reluctance to use C style casts.
>>
>> They can cast to reinterpret_cast but they also try out the weaker cast
>> before. It is just automatic way to do what you would do manually - first
>> try const_cast, then static_cast and finally reinterpret_cast... yes, it can
>> use reinterpret_cast but you would have to use it anyway in a particular
>> case where you really need it.
>>
>> So what's wrong with little automation, providing that you know what you are
>> doing with casts?
>
> Perhaps a story would help you understand.
>
> A while back I worked under a guy who used C++ but basically feared
> everything about it.  Boy did he love inheritance though.  He used
> inheritance as his only method of code reuse.  He created these
> gigantic higherarchies

[snip excellent thedailywtf.com material]

Sometimes I wonder if the critics aren't right after all -- that C++
is too complicated for its users to understand. But then so is any
other language, damn it!

/Jorgen

PS. Interesting spelling of "hierarchy". Still unsure if its
    intentional ;-)

-- 
  // Jorgen Grahn <grahn@  Oo  o.   .     .
\X/     snipabacken.se>   O  o   .

[toc] | [prev] | [next] | [standalone]


#9415

FromNoah Roberts <roberts.noah@gmail.com>
Date2011-08-28 13:41 -0700
Message-ID<45c702d0-ae3c-4618-9152-0b476301a38f@b9g2000prd.googlegroups.com>
In reply to#9413
On Aug 28, 12:44 pm, Jorgen Grahn <grahn+n...@snipabacken.se> wrote:
> On Sat, 2011-08-27, Noah Roberts wrote:
> > On Aug 26, 5:40 am, "A" <a...@a.a> wrote:
> >> I do not understand though reluctance to use C style casts.
>
> >> They can cast to reinterpret_cast but they also try out the weaker cast
> >> before. It is just automatic way to do what you would do manually - first
> >> try const_cast, then static_cast and finally reinterpret_cast... yes, it can
> >> use reinterpret_cast but you would have to use it anyway in a particular
> >> case where you really need it.
>
> >> So what's wrong with little automation, providing that you know what you are
> >> doing with casts?
>
> > Perhaps a story would help you understand.
>
> > A while back I worked under a guy who used C++ but basically feared
> > everything about it.  Boy did he love inheritance though.  He used
> > inheritance as his only method of code reuse.  He created these
> > gigantic higherarchies
>
> [snip excellent thedailywtf.com material]
>
> Sometimes I wonder if the critics aren't right after all -- that C++
> is too complicated for its users to understand. But then so is any
> other language, damn it!

Perhaps C++ puts too much power in the hands of people who can't use
it responsibly, but I think also that there are many people who will
just write crap code no matter what language they're using.  I mean,
the person in question actually told me that, "The document/view
architecture is considered outdated," when I suggested we NOT mix
business and UI code into the same classes.  Using Java or C# or some
other supposedly "easy" language would not have made his code any
better, it only perhaps would have lessened some of the consequences
regarding poor casting.  Even then though, I seriously doubt it would
have made any difference.

I'm currently working with someone who seems to think globals are the
best thing since sliced bread and is actually AGAINST factoring them
out of functions that could easily work with parameters instead.  This
time the language is C, which is supposedly "simpler" than C++ (which
again seems to be hated).  Put such a developer in "simple", weakly-
typed language or something and he'll do the same thing...it just
doesn't matter.  In fact in many cases it may get much worse because
now they're not limited to multiple uses of the same type when multi-
purposing a global variable...they can use it as a string here and a
double over there.

The casts that C++ offers introduce a small safety against some of
what can happen when people do bad things, which EVERYONE does.  The C
style casts just are not equipped for the introduction of things that C
++ adds to C, like multiple-inheritance and stronger typing.  They
won't fix broken coders though and I really don't think that C++ is to
blame for the kinds of poor approaches I've seen in the industry, with
surprising frequency and at surprisingly high levels of authority.  A
good language might protect you from making basic mistakes in grammar
or semantics, but if your statements are nonsense to begin with then
no amount of simplicity is going to create sense of them.

[toc] | [prev] | [next] | [standalone]


#9339

FromAnand Hariharan <mailto.anand.hariharan@gmail.com>
Date2011-08-26 07:30 -0700
Message-ID<849a55ff-43e2-4f8c-ad5e-826044ae6a01@g9g2000yqb.googlegroups.com>
In reply to#9331
On Aug 26, 3:05 am, "Duga Chernobyl" <duga...@gmx.com> wrote:
> Dnia 25-08-2011 o 23:58:56 A <a...@a.a> napisał(a):
>
> > int Callback(void *pThis)
> > {
> > TMyClass *pMC = (TMyClass*)pThis;                    // C style
>
(...)
> The first is used in c and should be used only in C.

The cast is not needed in C.

- Anand

[toc] | [prev] | [standalone]


Page 3 of 3 — ← Prev page 1 2 [3]

Back to top | Article view | comp.lang.c++


csiph-web