"Say, um, you got a minute?"
I recognized the timid voice behind me. Kerry, our department's new intern, was standing at my cubicle. He was bright enough, but... man, what a geek. I had told Wendy so, but she had only muttered something I didn't quite catch about pots and kettles.
"Yeah, sure," I swung around to face him. I didn't have a whole lot more experience under my belt than Kerry did, but it felt good to be regarded as an experienced hand. I was ready for anything he could throw at me.
"What's the speed-dial code for our London office?"
I sighed. So much for being the guiding expert. I jotted the code down on a sticky note and handed it to him.
"Thanks," he said as he turned. "I have to ask Bob something."
Danger, Will Robinson! My heart leaped into my throat as I leaped to my feet. "Don't!" I blurted. Kerry froze in his tracks. "That is, don't bother asking him. I mean uh," think fast... think fast... "don't bother him. I'm sure we can handle it."
"But Bob said I should leave you alone," Kerry stammered out. "Before he left, he said if I had any questions, I should call him. He said, 'Whatever you do, make sure you stay way from...' "
"Oh, look at the time," I interrupted. "It's way past quitting time in London. Bob'll be long gone."
"But it's only 3:30 there."
Yeah, that's about quitting time for Bob, I thought. Out loud, I said, "Bob... works early shifts when he's in London."
"Oh. Well, I suppose it'd be OK," Kerry didn't seem too convinced, but he did sit in my guest chair. "The problem is, I have a function that takes a typedef of a pointer," he said, as he wrote on the whiteboard:
typedef T* Tptr; void f( const Tptr t ) { *t = T(); // don't want this, but it's allowed }
"Inside the function, I can modify t, even though I've declared it const. I also tried Tptr const t, but it didn't work either. I know if I wasn't using the typedef, I could write const T * t, and that'd do what I wanted."
"Ah," I said, stalling for time as I thought about this. I knew I'd come across this before. But where? When? "Well, a typedef isn't quite like a macro text substitution. I don't recall the ins and outs of it, but I do remember that if you write it with the const qualifier after the type, it behaves more like you'd expect." I modified his code slightly:
void f( Tptr const t ) // still means T* const
Kerry squinted at the new code. "But Tptr const t is different from const Tptr t. Isn't it?"
A new voice said: "No! No different."
I jumped slightly at the Guru's voice behind us. Kerry squeaked as he shot out of his chair. The Guru continued calmly, closing the thick book in her hand and ignoring the reaction: "Tell me, young learner, what is the difference between int const i and const int i?"
Kerry's eyes were wide so wide, that I started wondering what Bob had said to him about the Guru. For her part, the Guru seemed not to notice his trembling.
I decided now would not be a good time to participate in the Guru's act: "They're the same thing. Aren't they, Kerry?" I prompted. Kerry nodded dumbly.
The Guru's brow furrowed slightly. "So, if const int and int const the same are, expect you Tptr const and const Tptr to be different, do you? Hmm? And well you should not."
"Uh, yes, I was explaining that part," I cut in, remembering. "Okay, Kerry, in this code, what's const?" I wrote:
const int i; // or int const i;
"The int," Kerry said slowly. The simplicity of the question brought him round.
"Okay," I nodded. "Now in this code, what's const, even if T is a typedef?" I wrote:
const T t; // or T const t
"The T object," Kerry said, more confidently now.
"Good. Now in this code, what's const?" I wrote:
const Tptr t; // or Tptr const t
"The..." Kerry trailed off. "Oh. The Tptr?"
"Right. But the Tptr represents a compound type, and the const can only apply to one of part of the type. The pointer itself is const; this is the same as T* const. Now, just one more: in this code, what's const? I wrote:
const T* t; // or T const* t
"The... object pointed at," he got out.
"Right," I concluded and set the whiteboard marker down. "That's the difference between const Tptr and const T*.
The Guru placed a hand on my shoulder briefly and took over again: "This, indeed, is one reason a few prophets [1] say to put the const keyword as far to the right as you can without changing the meaning of the declaration. Then you can mentally expand the typedef as if it were an unholy macro," she shuddered, "to get the correct meaning."
"Yeah, but I've always thought that's backwards," I complained. "I want to declare something like 'const int * iptr' because when I read it, I can say 'constant int pointer iptr'. Almost everybody, including all the books, writes it that way. The other way feels backwards."
"Backwards?" the Guru arched an eyebrow. "Although we neither recommend nor disclaim the 'const to the right' style, the pious one's argument has some merit. It can make reading the declaration easier."
"How?" asked Kerry.
"Read it the way of the compiler, you must. What you are really saying is 'iptr is a pointer to a constant int', which from right to left is exactly what 'int const * iptr;' declares to the world."
"But, so, how do I declare my function so that the T object really is constant?" Kerry asked to get back to his original question.
"Ah, my child, quite simply." The Guru wrote:
void f( const T* t )
"But I really want to use a typedef," Kerry protested.
"Ah, the rub. If a typedef you must have, a separate typedef for a constant T you need:"
typedef const T* Tcptr; void f( Tcptr t )
"Beware, though," the Guru added ominously, "we have found that using a typedef simply to create a pointer adornment adds very little value. Because of the const limitations we have discussed, you must provide two separate typedefs. Such a proliferation of typedefs with very little difference in meaning can serve only to confuse the unwary. This too is vanity."
The Guru reopened her book, turned, and glided away. "Confusion is the dark side of programming. Too many typedefs, poor naming choices these all lead to..." Her voice faded as she disappeared around a corner.
I looked at Kerry. He stared at me and gulped.
"Don't worry," I said reassuringly, "you'll get used to her. She really is an excellent programmer." Kerry blinked, opened his mouth, closed it, and wandered off in a daze. I shrugged and went back to work.
References
Jim Hyslop is a senior software designer at Leitch Technology International Inc. He can be reached at [email protected].
Herb Sutter (<www.gotw.ca>) is secretary of the ISO/ANSI C++ standards committee, author of the acclaimed books Exceptional C++ and More Exceptional C++, and one of the instructors of The C++ Seminar (<www.gotw.ca/cpp_seminar>). In addition to his independent writing and consulting, he is also C++ community liaison for Microsoft.