April 2008

Fun with C++: Useless Consts?

Many C++ programmers see the keyword “const” as something redundant that only gets in the way. They curse Stroustrup and his ancestors each time they encounter a const-related compile error because of that view and fail to use it correctly quite often (note that I’m not saying that I’m not one of these people, but I curse neither Stroustrup nor anyone else.)

If you ask them about the purpose of the const keyword, they would give you the classic answer that any C++ textbook gives: variables declared as consts cannot be changed by the programmer, and const class methods cannot modify their instance data (and can be called on const class instances), etc.

The programmer may give you the textbook answer (or some mutilated version of it, depending on which textbook she read and how much of it she actually remembers,) but she is wondering with herself who will stop the other programmer to change the header file and remove the const from the declaration? Who is there to prevent her from doing so?!

She may even make a conjecture that if she removes all the consts from all her source files and headers (including standard and 3rd party headers she uses,) then her programs will continue to compile and work just fine (after all, the const keyword has no runtime effect. It’s an exclusively compile-time construct, is it not? So if her programs used to work, and they compile after removing all consts, they should continue to run without problem.)

If she is a little bit more sophisticated and skilled in C++, she knows that the C++ compilers differentiates between functions that take const arguments and those that take exactly the same arguments, but not const. This fact lets you have function overloads that only differ in constness of their arguments. The same is also true for template specializations (which is a form of overload anyway.)

So this more sophisticated C++ programmer will conjecture that if she removes all the consts and eliminates the redundant overloads (which were nothing but nuisances to begin with) then her programs will compile.

Now, is she right? Is this the case with const?
(I should say that I know of one case that is not so (the program will not compile without the the const) but it’s not a common case. I’ll write about that in a later post (if no one guesses it first.) I’m genuinely interested in other such cases.)
(Another note. The use of const frees the compiler to do some optimizations that may not be safe with a non-const object. My question is about correctness and not about performance.)

C++
code
programming

Comments (2)

Permalink

“Fly Oceanic,”…[pause]… Not!

If you watch LOST and like it (as I do,) you know that the flight they were in and crashed was Oceanic flight 815.
I was watching a movie, “Executive Decision” which is a typical terrorists-hijack-airplane film (and not a very good one.) The plane they hijack in that movie is Oceanic flight 343! So I got curious. A quick search on Google turned up oceanic-air.com!
Right on the front page it says that the airline has gone bankrupt and is closed. This was quite a shock for me! The I noticed that it says that they went bankrupt following the incidents following the accident of flight 815! And also I noticed that their logo looks familiar. To sum it up, the website is a humorous publicity act to promote LOST.
It turns out that, according to this page, the Oceanic airline is the canonical airline-in-trouble used in the film business!

entertainment
noteworthy

Comments (0)

Permalink

Spam (no parrots or the Spanish inquisition!)

According to this article on ITNews, of all the email that has been sent globally in the first three months of 2008, around 92% have been spam!
At first, this number seemed too high to me too. But I checked my email junk folders and logs and now I have to agree with this piece of statistics.

noteworthy

Comments (0)

Permalink

Fun with C++: When Parentheses Don’t Call!

Just a quick one. Most of us have come to think of parentheses as sometimes necessary but always harmless little creatures. Our view is that unless parentheses change the order of evaluation (and therefore the meaning) of an expression, they are completely harmless.
Well, while that is true almost by definition, there are cases that we might not realize the meaning of an expression is being changed. One such case is in the presence of the versatile and extremely useful (and possibly massively pain inducing) comma operator (’,‘.)
You see, the comma has two uses in C++ language: as an operator and as a separator for many different lists of things in the language grammar (function arguments, object declaration, etc.) In the first context, a pair of parentheses work exactly as anyone would expect; in the second, probably not. The problem is that the use of commas in the first context is not common at all, while the commas of second kind riddle any and every C++ source file. It’s mixing the meaning of the uses that’ll lead to potentially cryptic compile errors (what a shocker! Cryptic compile error messages in C++?!), or worse, logical bugs that will make you wish you were coding in machine language.

Just for the sake of comprehensiveness, while I know that you all know how the comma operator operates, I’m gonna describe its workings anyway. The comma operator has the lowest precedence among all the operators in C++ and it is a left-associative operator (meaning “a, b, c” will be evaluated as “(a, b), c“.)
An expression of the form “a, b” (where a and b are expressions themselves (and not statements)) will always evaluate a first, and then b and will return the evaluated value of b.
Please believe me when I say that overloading this operator can achieve magic and convenience one can only dream of in C++! Just see the Boost.Assignment library for a sample.

One place that the implicit mixing up of the meaning of comma could cause trouble is in function calls. Suppose that a function X accepts two arguments. Now, if instead of X (a, b) someone writes X ((a, b)) then they will be given a compile error saying that function X does not take one argument(s);-) . This is because the extra pair of parens have changed the meaning of the comma from a simple argument list separator to a C++ operator.
This will not confuse any C++ programmer out of her first few months with the language, and will be obvious and easy to find and fix. But what if the extra pair of parentheses is the result of a macro expansion? Then you’ll have to chase down the macro definition. Still not very hard, because the compiler will catch you. But what happens if the X function has an overload with a single argument, incidentally with a type compatible with b? What happens if the function takes more than two arguments and has many overloads and it’s called like this: X (a, (b, c), d, (e, f, g))?
I should probably list this as another macro pitfall. Take care where you put parentheses! Don’t just slap them whenever you’re in doubt!

C++
code

Comments (0)

Permalink

Crimson of Home

There’s a corridor in my house (actually, my mom’s house) at the end of which are the bedrooms. The bedroom right in front of the corridor has its door and window in line with it and has a thick red curtain (with an almost perfect Lambertian material, as they’d say in the graphics programming business!) on that window. The corridor is facing south so there’s light behind this curtain during almost all hours of the day.
Every time I return from a trip, if the Big Yellow Light in the Big Blue Room is on, the light passing through the curtain casts a really really eerie red-colored mood into the place. It’s not ominous or anything; quite the opposite. It is soothing and comforting. It’s the sign of home for me.

life
rants

Comments (0)

Permalink

C++ “Glasses”!

The Slashdotters put together a list of questions for Bjarne Sroustrup to answer a while back. The Q&A is interesting on its own, but this comment by an anonymous coward (as they are called on /.) is the funniest piece of writing I’ve read in a long time!
Read the Q&A and the rest of the comments too, if you have time.

C++
hilarious
noteworthy
programming

Comments (3)

Permalink

Fun with C++: Metaprogramming, Part 1

Metaprogramming can mean many things, but all of them can be made to (loosely) fit under the description of “writing programs that write or rather describe (a class of) other programs.” A classic and somewhat useless sample of this is writing a program that prints it’s own source code. My first real contact with this field came from working with YACC. The rule file one writes to be fed to YACC, is kind of a metaprogram.
As a better example, if you could write a program that would accept a set of strings and generate a C++ program that would implement a “perfect hash function” that would hash those N input strings onto N collision-less values, then you’d have written a metaprogram. (Note that you are not implementing a hash function; you are writing a program that implements many hash functions based on the input.)

Now, these metaprograms can be in any language and output any language. If you write one in C++ that produces C++, then you have to run your compiler twice to get to the final usable program. Not really convenient, but it is used in the real world. For example, that perfect hash function generator example is exactly how gperf works.
On a cooler side, there’s already a couple of other mini-languages that any C++ compiler package can understand, e.g. the preprocessor language. I’m the first one to admit that writing a program only in preprocessor is like having trying to open a locked door with your head, but it’s not entirely without merits and fantastic experiences.

OK, so let’s get down to it. Before we can program in any language, we should know how some basic ideas like logic, conditions, repetition, etc. are expressed in that language. First off, doing loops a la “for” and gang is really really hard to do in preprocessor (I’d say impossible, but I’ve seen Boost.Preprocessor!) Fortunately, C++ preprocessor language does support a form of recursion (guess how?) and we can use that facility both as loops and as subroutines.
If you think about it, you’ll find out that the preprocessor’s programming model is not unlike digital logic circuits, with all the variables, inputs and outputs being single bits (whether a specific macro has been #defined or not) and the only operations being ANDs, ORs and NOTs. Although the preprocessor can assign arbitrary integers to macros and can compare them, but cannot do arithmetic on them.
As a first example, let’s see how an XOR logical function with two one-bit inputs can be implemented.

1
2
3
4
5
#if (defined(IN_a) && !defined(IN_b)) || (!defined(IN_a) && defined(IN_b))
    #define OUT_a
#else
    #undef OUT_a
#endif

That’s it. Not very complex or revolutionary, but this idea can be taken far. What if we put the above code in a header file, and #include that header whenever and wherever we need a 1-bit XOR? Of course, the parameters to that XOR are always the same (think of them as global variables) but this concept can be use to implement functions and therefore recursion. I’m not going to go into more elaborate examples of recursion. Just let me demonstrate a little more of the preprocessor with another example that actually does something and generates output. I’ve implemented a 1-but full-adder (three inputs: A, B and Carry, and two outputs: A and Carry. The input carry is for reusability.) This example consists of two files; a “OneBitAdder.h” like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/*
	OneBitAdder.h
 
	Inputs: "IN_X" and "IN_Y" and "IN_C"
	Outputs: "OUT_X" and "OUT_C"
 
	Returns the sum of the inputs. Note that each input and
	output here is one bit: either a macro is defined (it's 1)
	or not (it's 0.)
*/
 
  #if !defined(IN_X) && !defined(IN_Y) && !defined(IN_C)	// 0
	#undef OUT_X
	#undef OUT_C
#elif  defined(IN_X) &&  defined(IN_Y) &&  defined(IN_C)	// 3
	#define OUT_X
	#define OUT_C
#elif  defined(IN_X) && !defined(IN_Y) && !defined(IN_C)	// 1
	#define OUT_X
	#undef OUT_C
#elif !defined(IN_X) &&  defined(IN_Y) && !defined(IN_C)	// 1
	#define OUT_X
	#undef OUT_C
#elif !defined(IN_X) && !defined(IN_Y) &&  defined(IN_C)	// 1
	#define OUT_X
	#undef OUT_C
#else						// 2
	#undef OUT_X
	#define OUT_C
#endif

and the “PreprocessorAdderTest.cpp“:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// Set input
#define IN_X
#undef IN_Y
#define IN_C
 
// Compute
#include "OneBitAdder.h"
 
// Display(!) output
#  if !defined(OUT_X) && !defined(OUT_C)
	#pragma message ("--- The answer is 0")
#elif  defined(OUT_X) && !defined(OUT_C)
	#pragma message ("--- The answer is 1")
#elif !defined(OUT_X) &&  defined(OUT_C)
	#pragma message ("--- The answer is 2")
#elif  defined(OUT_X) &&  defined(OUT_C)
	#pragma message ("--- The answer is 3")
#endif	
 
// main is mainly cosmetic.
int main () {return 0;}

I’ve used #pragma message for output here. I’m not sure which compilers support it (I suspect all that matter) but if you want you can use other methods, like using #error.
Create these two files and compile the “.cpp” file (note: just compile it.) There should be a string “— The answer is 2” in your compiler output! See what we did? We just run a program by compiling a C++ source file! Cool, eh?

Of course, getting any real use out of the preprocessor (beside the obvious) is really is not worth the effort, but if you want to see whether you have the hang of it, try writing a 2-bit adder using the above 1-bit adder. It’s not as easy (nor as hard) as it may sound. The samples here were not really good examples for metaprogramming, but I think you can extrapolate from here on if you want to.

I originally (i.e when I started writing this post!) wanted to write about template metaprogramming, but I went in a completely different direction. Maybe next time then.

C++
code

Comments (4)

Permalink

How Many Times Must the Cannon Balls Fly?

Do you ever look at the horizon and see the clear sky, and yet know that there’s a storm coming? I know this never happens outside of movies, but I’m not talking literally here.
Do you ever get the feeling that the world we live in, or better yet, the country we live in is on the verge of anarchy? Do you feel that we are so close to an explosion that will again shake this already shaken and injured people to their bones? Do you hear the prayers of them for mighty storms to wash away the filth on the surface of the stale pond? Do you fear that the great storm will mix the filth right into the water and will raise the scum at the bottom to the surface?
Do you think there’s a storm coming?
The answer, my friend, is blowing in the wind…

rants

Comments (3)

Permalink