tags:

views:

327

answers:

5

let's say I have:

set<int, less<int> > m_intset;

that works, but now I change it to typedef, and if I do I end up with two lines of code, right?

typedef set<int, less<int> > SetInt;
SetInt m_intset;
  1. So, what's the use?
  2. Is that the way to change it and use it?
+4  A: 

You have it exactly correct. Using a typedef makes it easier to use things like SetInt::iterator.

Mark Ransom
Surprising that this is at the top as the answer provides no information as to *why* a typedef is useful, which was the original question.
Ed Swangren
It's easier because there's less typing.
jmucchiello
@jmucchiello: That is not the true purpose of typedef's.
Ed Swangren
Easier to type is also often easier to read. Not always, but it is in this case. That's often enough justification. Short answers are also easier to read.
Mark Ransom
+2  A: 

The benefit is when you refer to the same type multiple times. For example, if you want to iterate over your set; compare:

for (set<int, less<int> >::iterator i = xs.begin(); i != xs.end(); ++i)

with:

for (IntSet::iterator i = xs.begin(); i != xs.end(); ++i)

The difference gets more pronounced if you have nested template parameters (e.g. a set of pair of vector of string).

Pavel Minaev
+1  A: 

You are creating an alias to a type to be used in a specific context. How about this example:

typedef int INT32

That's all well and good, and if you only ever compiled for environments where an int was a 32-bit quantity you would not even need it. However, perhaps, some day in the future, you port your code to a system where a native int is 64 bits. Now your code may have some bugs if it assumes a 32-bit size for int's everywhere they are used. With the typedef, you need only change the argument:

typedef /*some 32 bit type*/ INT32

Note that this is only an example. The idea is abstracting the type away if it may change in the future or clears up your code.

Ed Swangren
It's not really a new type, more like an alias (the distinction is important for purposes of overload resolution and template instantiation).
Pavel Minaev
Yes, that's true, edited.
Ed Swangren
@Ed: Minor nit, but you've got the syntax backwards (should be typedef int INT32;)
Drew Hall
Bah, this is what I get for writing rushed answers :)
Ed Swangren
+3  A: 

Typedef's are mostly notational convenience, but they do have a bunch of benefits:

  • Declaring function pointer types (e.g. for callbacks)--notoriously hard to get right when spelled out completely.
  • Dependent type information is easier to describe (e.g. SetInt::iterator) and should you ever change your mind (suppose you went to a hash_set instead of a std::set), is effectively updated immediately due to the typedef
  • They describe intent better than built-in typenames do (e.g. typedef int ErrCode)

I'm sure there are more I'm not thinking of....

Drew Hall
One case I know of where there's no way to do it without a `typedef` is when you need a function with C++ calling convention to take an argument or return a value of a function pointer type to a function with C calling convention. You can't use `extern "C"` on individual arguments, and applying it to function as a whole will apply to all its arguments as well as the function itself. The only workaround I know of is to make a `typedef` for the function pointer type inside `extern "C" { ... }`, and then use that.
Pavel Minaev
Another bit of "typedef trivia" similar to Pavel's (from a recent SO question that I can't readily find now): you have to use a typedef'd name if you want to use a C++ 'constructor-style' cast for some types. For example, `int( 10.)` works as a cast to `int`, but `char*(p)` doesn't as a cast to a `char*`. But with a `typedef char* charptr_t;` this does work: `charptr_t( p)`. Yeah, I know; I said it was trivia.
Michael Burr
+9  A: 

Some advantages to using typedef:

  1. Simplification: Now, every time you would normally have needed set<int, less<int> >, you only have to type SetInt. Not a big deal if you're only using the set once, but if you've got multiple instances of the same set, or need to access iterators thereof, the shorter form is much easier to read and type.

  2. Clarification: set<int, less<int> > doesn't tell me anything about what the variable is used for, just that it's a set of ints. With typedef, you can choose an identifier that explains the purpose of the type, such as Inventory or Coordinates, for example.

  3. Abstraction: Programs change. Although you may think you need a set<int, less<int> > now, there's always the possibility that your requirements may change in the future, necessitating a set<unsigned long, less<unsigned long> > or vector<int> or some other change. By using a typedef, you would only have to fix this in one place, and it will affect every instance of SetInt in the program. This is far simpler and less prone to error than manually changing a dozen or more entries in the source files.

Due to points 2 and 3 above, typedef can be very powerful when used inside a class or a library, since it can strengthen the separation between interface and implementation which is generally considered good C++ form.

Of course, most of these advantages only really show themselves if you're using the same type multiple times in the same program. If you only expect to use the set<int, less<int> > once, typedef is probably overkill.

goldPseudo