

C++ Streams & Typedefs: Be Charful - humbledrone
http://blog.mezeske.com/?p=170

======
makecheck
I don't think focusing on a particular case is helpful, because what they're
really talking about is _the entire C++ type system_. This could happen in any
case where types are converted: calling functions, assigning
variables...whether or not any printing or typedefs or chars are involved. You
could see surprising behavior anywhere, and arguably in places where it is a
lot harder to debug.

The "explicit" keyword for constructors addresses part of the problem, but not
all of it. The real issue is one of programming style. Personally, I feel this
is a case where C++ programmers should think more like C programmers, and not
be offended by having to give functions different names, or otherwise making
things more distinct when _the behavior is totally different anyway_.

If I have to call handleChar() and handleInt() with an "if" statement, instead
of relying on one of the 12 overloads of handleAnything() to perform magic, I
think that is _fine_ because it will one day save me hours of debugging.
Notice that printf("%c", c) has pretty damned clear behavior, and it requires
someone to say the equally-clear printf("%d", (int)c) to get a number when
they want a number; this might not be C++-like, but it's the right way to
think about the problem.

~~~
nuxi
> Notice that printf("%c", c) has pretty damned clear behavior, and it
> requires someone to say the equally-clear printf("%d", (int)c) to get a
> number when they want a number;

It does have a clear behaviour, but it's possibly different from what you
think. From your examples I'm assuming "c" is a char variable - since you're
casting it to int in the second example - which is then (incorrectly) passed
to printf with "%c". Both %c and %d require an integer parameter, so "c"
should be an integer to begin with (thus no need for a cast).

Nitpicking, I know, but such code can lead to many subtle bugs.

~~~
makecheck
The C library should cast the parameter down to a char when "%c" is used; the
only reason it allows an int is for the "%lc" case.

~~~
nuxi
It does cast it down (to unsigned char). The requirement for int however was
is not for "%lc", it was already in C89. I suspect it has to do with default
integral promotions for (variadic) function parameters - which I incorrectly
disregarded when replying.

So the original code is correct, my reply wasn't.

------
joezydeco
Wh-at the he-ck is up with the brea-ks in this art-icle?

~~~
humbledrone
Are you using Chrome? If so, you might check the bug report at
<http://code.google.com/p/chromium/issues/detail?id=65941>.

~~~
joezydeco
Wow, that's a _browser_ bug? Thanks. (And yes, Chrome 80552)

------
anonymous246
IIRC, Pascal had the opposite problem. Typedefs were considered distinct even
if the underlying type was the same.

~~~
humbledrone
It would be really handy if C++ supported both its existing typedef behavior
(aliasing) and the Pascal kind (distinct copy). I wonder if any other strongly
typed languages (e.g. Haskell) support both kinds of behavior.

~~~
dododo
haskell does support it.

c style:

    
    
      type Foo = Int
    

pascal style:

    
    
      newtype Foo = Foo Int

