tags:

views:

538

answers:

7

I've seen code like the following frequently in some C++ code I'm looking at:

typedef class SomeClass SomeClass;

I'm stumped as to what this actually achieves. It seems like this wouldn't change anything. What do typedefs like this do? And if this does something useful, is it worth the extra effort?

A: 

It looks like the comment is trying to say that the typedef makes the symbol SomeClass global in a way that prevents anybody from being able to declare a local object with the same name that hides the original SomeClass.

I tried this out with VC6 (not a real C++ compiler I know, but the best I have ATM), and it doesn't seem to do much. SomeClass still gets hidden by a local declaration with the same name. Perhaps it changes the content of an error message for some compiler to make it more useful.

T.E.D.
A: 

I understand the concept of the different namespaces that tags and identifiers live in, but is this really even worth the trouble of typing it?

No.

Charlie Martin
(-1) Absolutely no explanation or reasoning. I could just as easily have written "Yes." and the only difference would have been reputation.
You don't like my answer (he, after all, laid out the reasoning), write your own.
Charlie Martin
A: 

It looks to me like your colleague may not have fully graduated from C.

In C, if you declare struct foo {int a;};, you don't have anything you can call just foo, but rather struct foo. Therefore, it's fairly common to typedef struct foo as foo.

This was changed in C++, for reasons that should be fairly obvious.

David Thornley
It's possible, but I wouldn't really call C's behavior "name hiding."
Neil Williams
+21  A: 

It prevents code like this from compiling:

class SomeClass { ... };
int SomeClass;

This is perfectly legal C++, though it's terrible. If you do this, then any references to a bare SomeClass refer to the variable. To refer to the class, you need to explicitly say class SomeClass at each usage. If you create a typedef:

class SomeClass { ... };
typedef class SomeClass SomeClass;
int SomeClass;

Then the compiler flags the definition of int SomeClass as an error, as it rightly should be.

Adam Rosenfield
Your second example compiles for me (VC2005).
Neil Williams
Problem with VC++ then - it should not compile.
anon
Interesting, it actually works with one compiler i use (and not with MSVC)
Dolphin
VC6 compiles it too. If you actually try to *use* it as a class the code blows up of course.
T.E.D.
I tried it with the Comeau online compiler and it failed as desired there. So I guess this must be why it's in the code. Still seems pointless to me since people should just not write code like that!
Neil Williams
@Neil, you can re-mark a correct answer, you know? check the voting...
jpinto3912
@jpinto I actually had this one marked as correct before, and though it answers why it's done, it doesn't actually answer if it's worth it. The makers of SO have said before that the community idea of "best answer" and the asker's idea of "best answer" can be different and that's by design.
Neil Williams
In any case, i upvoted both :)
Johannes Schaub - litb
This is interesting - the "typedef class SomeClass SomeClass;" example compiles fine in VC2008, VC6, and Digital Mars (but not in GCC or Comeau). This seems to clearly be illegal code being accepted by these compilers. I wonder if there's something in the Windows SDK that makes them accept this as an 'extension'?
Michael Burr
A: 

Either really broken compiler or someone not knowing what they do, or so I would think.

Joakim Elofsson
Or someone knowing something that many people don't know...
Michael Burr
+6  A: 

Adam has supplied the correct reason for doing this, but regarding your question "Is it worth the trouble" I would give a resounding "No!". The possible problem code:

class SomeClass { ... };
int SomeClass;

will be caught when a bit later on someone says:

SomeClass sc;

Admittedly the compiler will point at the "wrong" line, but this sort of thing happens so rarely (I don't think I've ever seen it in real code) that it can't justify a forest of near superfluous typedefs.

anon
Thanks for answering that question, that's what I really wanted to know. I'd never seen it done before, so I had a feeling it'd not be worth it.
Neil Williams
If you leave out the typedef you may not always get an error, though admittedly the situations would be rare. A function with the same name as a class can hide something that would otherwise be a class constructor.
Michael Burr
Could you post an example of this - I can't visualise how it would be possible.
anon
Neil - see my updated answer below: http://stackoverflow.com/questions/953166/what-is-the-purpose-of-typedefing-a-class-in-c/954445#954445
Michael Burr
+5  A: 

See this previous answer to a related question. It's a long quote from a Dan Saks article that explains this issue as clearly as anything I've come across:

http://stackoverflow.com/questions/612328/difference-between-struct-and-typedef-struct-in-c/612476#612476

The technique can prevent actual problems (though admittedly rare problems).

It's a cheap bit of insurance - it's zero cost at runtime or in code space (the only cost is the few bytes in the source file), but the protection you get is so small that it's uncommon to see someone use it consistently. I have a 'new class' snippet that includes the typedef, but if I actually code up a class from scratch without using the snippet, I almost never bother (or is it remember?) to add the typedef.

So I'd say I disagree with most of the opinions given here - it is worth putting those typedefs in, but not enough that I'd give anyone (including myself) grief about not putting them in.

I've been asked for an example of how not having a class name typedef'ed can result in unexpected behavior - here's an example lifted more or less from the Saks article:

#include <iostream>
#include <string>

using namespace std;

#if 0   // change to #if 1 to get different behavior
        // imagine that this is buried in some header
        // and even worse - it gets added to a header 
        //     during maintenance...
string foo()
{
    return "function foo... \n";
}
#endif

class foo
{
public:
    operator string() {
        return "class foo...\n";
    }
};

int main()
{
    string s = foo();

    printf( "%s\n", s.c_str());
    return 0;
}

When the function declaration is made visible, the behavior of the program silently changes because there is no name conflict between the function foo and the class foo.

However, if you include a "typedef class foo foo;" you'll get a compile time error instead of a silent difference in behavior.

Michael Burr
You have to do so many things wriong for this to happen that I'm tempted to say you deserve it! Number one would be providing conversion casts instead of using named functions (always a no-no, IMHO).
anon
Conversion operators might be a no-no, but they're not at all uncommon. Anyway, I won't argue the 'so many things have to go wrong' point. Like I said, it's not something I insist on in my or anyone else's code. But I wanted to explain why it's in the OP's code (that was the question after all), and point out that the typedef has no cost and causes no problems. In fact, it makes compilers act a little bit more like people expect - though I was surprised by the behavior of some compilers to Adam's snippet. I think the document linked by litb is educational in that regard.
Michael Burr
That's really interesting; the answers I've gotten to this question make me glad I asked this question on here.
Neil Williams