TITLE: the utility of typedef (Newsgroups: comp.lang.c++.moderated, 10 Nov 98) AUTHOR: hsutter@peerdirect.com (Herb Sutter) ------------------------------------------------------------------- Guru of the Week problems and solutions are posted regularly on news:comp.lang.c++.moderated. For past problems and solutions see the GotW archive at www.peerdirect.com. (c) 1998 H.P.Sutter News archives may keep copies of this article. ------------------------------------------------------------------- _______________________________________________________ GotW #46: Typedefs Difficulty: 3 / 10 _______________________________________________________ Congratulations to Andrei Alexandrescu, the Guru of the Week! >JG Question >----------- > >1. What does typedef do? Writing "typedef" allows you to assign another equivalent name for a type. For example: typedef vector< vector > IntArray; lets you write the simpler "IntArray" in place of the more verbose "vector< vector >". >Guru Questions >-------------- > >2. Why use typedef? Name as many situations/reasons as > you can. Here are several "abilities": Typeability ----------- Shorter names are easier to type. Readability ----------- Typedefs can make code, especially long template type names, much more readable. For a simple example, consider the following from a recent newsgroup posting asked what this code meant: int ( *t(int) )( int* ); If you're used to reading C declarations just like you'd read a Victorian English novel (i.e., something equally dense and verbose), you know the answer and you're fine. If you're not, typedefs really help, even with as meaningless a typedef name as "Func": typedef int (*Func)( int* ); Func t( int ); Now it's clearer that this is a function declaration, for a function named "t" that takes an int and returns a pointer to a function that takes an int* and returns an int. (Say that three times fast.) In this case, the typedef is easier to read than the English. Typedefs can also add semantic meaning. For example, "PhoneBook" is much easier to understand than "map< string, string>" (which could mean anything!). Portability ----------- If you use typedef'd names for platform-specific or otherwise nonportable names, you'll find it easier to move to new platforms. After all, it's easier to write this: #if defined USING_COMPILER_A typedef __int32 Int32; typedef __int64 Int64; #elif defined USING_COMPILER_B typedef int Int32; typedef long long Int64; #endif than search-and-replace for one of the system-specific names throughout your code. The typedef names insulate you from simple platform dependencies. >3. Why is typedef such a good idea in code that uses > standard (STL) containers? Flexibility ----------- Changing a typedef name in one place is easier than changing all of its uses throughout the code. For example, consider the following code: void f( vector& vc ) { vector::iterator i = vc.begin(); ... } What if a few months later you find that vector isn't the right container? If you're storing huge numbers of Customer objects, the fact that vector's storage is contiguous[*] may be a disadvantage and you'd like to switch to deque instead. Or, if you're frequently inserting/removing elements from the middle, you'd like to switch to list instead. [*] yes, I'm aware of the debate, and yes, it should be contiguous In the above code, you'd have to make that change everywhere "vector" appears. How much easier it would be if you had only written: typedef vector Customers; ... void f( Customers& vc ) { Customers::iterator i = vc.begin(); ... } and only needed to change the typedef to list or deque! It's not always this easy -- for example, your code might be relying on Customers::iterator being a random-access iterator, which a list